In java, say I have the following
==fileA.java==
class A
{
public static final int SIZE = 100;
}
Then in another file i use this value
==fileB.java==
import A;
class b
{
Object[] temp = new Object[A.SIZE];
}
When this gets compiled does SIZE
get replaced with the value 100, so that if i were to down the road replace the FileA.jar but not FileB.jar would the object array get the new value or would it have been hardcoded to 100 because thats the value when it was originally built?
Thanks,
Stephanie
Yes, the Java compiler does replace static constant values like
SIZE
in your example with their literal values.So, if you would later change
SIZE
in classA
but you don't recompile classb
, you will still see the old value in classb
. You can easily test this out:file A.java
file B.java
Compile A.java and B.java. Now run:
java B
Change the value in A.java. Recompile A.java, but not B.java. Run again, and you'll see the old value being printed.
Woo - you learn something new everyday!
Taken from the Java spec...
There is an exception to this:-
A.java
B.java
Actually I ran into this bizarreness a while ago.
This will compile "100" into class b directly. If you just recompile class A, this will not update the value in class B.
On top of that, the compiler may not notice to recompile class b (at the time I was compiling single directories and class B was in a separate directory and compiling a's directory did not trigger a compile of B)
The important concept here is that the
static final
field is initialised with a compile-time constant, as defined in the JLS. Use a non-constant initialiser (or non-static
or non-final
) and it wont be copied:(
null
is not a *compile-time constant`.)Another route to proving that the behavior is to looking at the generated bytecode. When the constant is "small" (presumably < 128):
(I used 42 instead of 100 so it stands out more). In this case, it is clearly substituted in the byte code. But, say the constant is "bigger." Then you get byte code that looks like this:
When it is bigger, the opcode "ldc" is used, which according to the JVM documentation "an unsigned byte that must be a valid index into the runtime constant pool of the current class".
In either case, the constant is embedded into B. I imagine, since that in opcodes you can only access the current classes runtime constant pool, that this the decision to write the constant into the class file is independent of implementation (but I don't know that for a fact).