5

Let's say I have a Java app which uses a (static) int constant from a library:

int myval = OutsideLibraryClass.CONSTANT_INT;

Now, without recompiling my app, I run it against a slightly different version of OutsideLibraryClass, in which the value of CONSTANT_INT is different.

Is my app going to see the new value (because it picks it up at runtime) or the old (because the value is compiled into the bytecode in my method)? Does it make any difference if CONSTANT_INT is final? Is there a part of the Java spec that talks about this?

DJClayworth
  • 26,349
  • 9
  • 53
  • 79
  • See also: http://stackoverflow.com/questions/1693091/public-static-final-variable-in-an-imported-java-class/1693135#1693135 – Dirk Jul 02 '10 at 17:02

4 Answers4

4

References to constant fields are resolved at compile time to the constant values they denote. (JLS 13.1)

Nulldevice
  • 3,926
  • 3
  • 31
  • 37
2

Unfortunately your question is not specific enough to answer the question, because it may or may not change without recompiling. Here's an example where the constant value will change with out recompiling.

public class Const {
   public static final int CONSTANT;
   static {
      CONSTANT = 4;
   }
}

class Test
{
   int c = Const.CONSTANT;
}

And here's a case where it will not change without recompiling

public class Const {
   public static final int CONSTANT = 4;
}

class Test
{
   int c = Const.CONSTANT;
}
MeBigFatGuy
  • 28,272
  • 7
  • 61
  • 66
  • Even though this wasn't the issue I was asking about, deserves +1 for reminding us that a constant has to be detectable as a constant by the compiler. – DJClayworth Jul 05 '10 at 13:25
1

No it will not pick up the new value. This is part of the language spec. See this question.

Community
  • 1
  • 1
Yishai
  • 90,445
  • 31
  • 189
  • 263
  • It depends on final modifier for CONSTANT_INT. – Nulldevice Jul 02 '10 at 17:23
  • 1
    @Nulldevice, if the field is called a constant, that directly implies a final modifier, IMO. And what kind of library would have a non-final public int anyway? – Yishai Jul 02 '10 at 17:29
1

From the JVM spec:

A class variable is a field of a class type declared using the keyword static (§2.9.1) within a class declaration, or with or without the keyword static in an interface declaration. Class variables are created when the class or interface is loaded (§2.17.2) and are initialized on creation to default values (§2.5.1). The class variable effectively ceases to exist when its class or interface is unloaded (§2.17.8).

So when the OutsideLibraryClass is loaded by the ClassLoader, the value gets initialized. When you perform your assignment statement on myVal, the value is loaded at runtime based on the OutsideLibraryClass class file that was loaded by the ClassLoader. So if you shut down the JVM, swap the jar file that contains OutsideLibraryClass and run it again, it will get the value from the new class.

UPDATE

The above statement is true if you're talking about an instance a local variable within a method. If your myVal variable is declared at the class level then the people saying it will not change are correct.

chrislatimer
  • 3,560
  • 17
  • 19
  • I did say 'static'. And referenced it as a static. – DJClayworth Jul 02 '10 at 17:48
  • I should have picked my words more carefully. I was referring to 'myVal' being a local variable within a method; I understood that you meant CONSTANT_INT was final static. If you take your exact statement and move it to a class level instance variable, you will not pick up the new value when you swap jars. If you take the same statement and put it within a (non static) method, you will pick up the new value when you swap the jar files. – chrislatimer Jul 02 '10 at 18:45
  • Have you tried this? Puzzle 93 from Java Puzzlers seems to say that the value is fixed at compile time if myval is either a local or instance variable. – DJClayworth Jul 02 '10 at 19:05
  • I wrote a test program to verify the behavior right before I posted the update. – chrislatimer Jul 02 '10 at 19:18
  • I do not claim to be an expert on the JLS, so if someone has a better explanation I'd be interested to enhance my understanding, but I think this statement from JSL 8.3.2 may explain the local vs. instance/class variable behavior here: "Variable initializers are also used in local variable declaration statements (§14.4), where the initializer is evaluated and the assignment performed each time the local variable declaration statement is executed." – chrislatimer Jul 06 '10 at 13:38