What is a compile time constant? (Beginning Java forum at Coderanch) (original) (raw)
It is amazing how many times a question comes up in this forum, where the answer is something like... "Because X is a compile time constant, the compiler will Y"... But what exactly is a compile time constant? And how can we determine whether something is treated as such?
Obviously, a compile time constant is a constant value that is known at compile time... ... Literals are, by definition, compile time constants -- as they are constants, known at compile time.
But the definition of a compile time constant is a bit more complex. To start, let's examine section 15.28 of the Java language specification.
15.28 Constant Expression
A compile-time constant expression is an expression denoting a value of primitive type or a String that is composed using only the following:
- Literals of primitive type and literals of type String
- Casts to primitive types and casts to type String
- The unary operators +, -, ~, and ! (but not ++ or --)
- The multiplicative operators *, /, and %
- The additive operators + and -
- The shift operators <<, >>, and >>>
- The relational operators <, <=, >, and >= (but not instanceof)
- The equality operators == and !=
- The bitwise and logical operators &, ^, and |
- The conditional-and operator && and the conditional-or operator ||
- The ternary conditional operator ? :
- Simple names that refer to final variables whose initializers are constant expressions
- Qualified names of the form TypeName . Identifier that refer to final variables whose initializers are constant expressions
This is the full definition of a compile time constant. And as you can see, it contains more than just literals. In fact, literals are merely the first bullet point on the list. Also, note that a compile time constant can apply to any literal that is of primative or String type.
The next few bullet points are the operations that can be applied to a constant at compile time. This list is actually pretty long, as it is possible to apply most of the operations at compile time. It may actually be easier to remember what can't be apply at compile time -- pre and post increment and decrement, instanceof operator, or any method calls, are not on the list.
The last few bullets are the most interesting. It is possible to use a variable in the expression -- provided that the variable is a compile time constant variable. So... what is a constant variable? Going back to the JLS (section 4.12.4 to be exact)...
4.12.4 final Variables
A variable can be declared final. A final variable may only be assigned to once. It is a compile time error if a final variable is assigned to unless it is definitely unassigned (§16) immediately prior to the assignment.
[BLAH BLAH BLAH]
We call a variable, of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28) a constant variable. Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1, §13.4.9) and definite assignment (§16).
The last part of the definition is the relevant part (I still find it amazing that this is that well hidden in the specification). To be a variable that is a compile time constant, the variable needs to be...
- declared as final
- have a primative or String type
- initialized (on the same line as the declaration)
- assigned to a compile time constant expression
Obviously, I am somewhat bored this morning... ...But hopefully... now when someone say, "what's a compile time constant", or "because X is a compile time constant", you know the long specification definition of what it is.
Hope this helps,
Henry