0

I've discovered that when a constant (static final, initialized at compile time) is declared in one project, references to it in another project are replaced by a literal when compiled.

It seems the only way to avoid this and have references refer to the constant field rather than the literal is to declare the constant in a class (as opposed to an interface) and omit "final," e.g.:

public class MyClass {
   public static String MY_CONSTANT = "The constant value";
 }

Unfortunately I coded an interface full of constants before I understood this, and now to effect a change in a constant, we have to identify all projects that refer to it and recompile them. I'm afraid something will slip through.

Also, a constant without the "final" modifier isn't exactly constant, is it?

Is there a compile option that can suppress the replacement of constant references by literals?

Elly
  • 63
  • 8
  • You discovered a hole in your knowledge about java. And for the record: yes, this is somehow a problem in larger setups, **but** this is a well-known problem. Any reasonable **build system** should be able to deal with that; by **understanding** the dependencies and the need to recompile all classes that need to ... – GhostCat Sep 27 '16 at 13:52
  • We had done the same mistake not so long ago. We than had change the Interface to have getter-Methods. and an implemting class. Please take a look add "Effective Java" from Joshua Bloch. Item 19: "Use interfaces only to define types" – Tobias Otto Sep 27 '16 at 13:59

1 Answers1

3

You just need something that isn't a compile-time constant expression. For example, method invocations aren't. So just adding .intern() at the end of each literal will make it escape the rules. Then each referring site will have to ensure the target type is initialized and read the current value.

A compiler option that changes this behavior is impossible because it would violate the Java Language Specification.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436