class A {
public static final String x = "foo";
public static String y = "bar";
}
class B {
public static void main(String[] args) {
System.out.println(A.x);
System.out.println(A.y);
}
}
You compile both classes and run B - you get an output as follows:
foo
bar
And then you change A thusly:
class A {
public static final String x = "baz";
public static String y = "qux";
}
and compile only A. Then run B. The output?
foo
qux
What just happened? The compiler is in-lining the static final x, but not y. Well, that comes from the Java language spec.
Scenario #2:
public abstract class A {
public A() {
System.out.println(bar().getClass());
}
public void foo() {
// do something
}
public abstract String bar();
}
public class B extends A {
final String value = getBar();
public String bar() {
return value;
}
private String getBar() {
return "barvalue";
}
public static void main(String[] args) {
System.out.println(new B().bar());
}
}
// invoke it
new B().foo();
Throws NullPointerException, but why? If you decompile B.class, you will find:
public class B extends A {
String value = null;
public B() {
super();
value = getBar();
}
public String bar() {
return value;
}
private String getBar() {
return "barvalue";
}
public static void main(String[] args) {
System.out.println(new B().bar());
}
}
So as it turns out, "final" variable is a compiler trick, as are keywords like "private" and "protected". You better be watching your Java compiler.