public class PrintWords {
public static void main(String[] args) {
System.out.println(Words.FIRST + " " +
Words.SECOND + " " +
Words.THIRD);
}
}
public class Words {
private Words() { }; // Uninstantiable
public static final String FIRST = "the";
public static final String SECOND = null;
public static final String THIRD = "set";
}
现在假设你像下面这样改变了那个库类并且重编译了这个类,但并不重编译客户端的程序:
public class Words {
private Words() { }; // Uninstantiable
public static final String FIRST = "physics";
public static final String SECOND = "chemistry";
public static final String THIRD = "biology";
}
此时,客户端的程序会打印出什么呢?
一个常量变量的定义是:一个在编译期被常量表达式初始化的final的原始类型或String类型的变量[JLS 4.12.4]。在知道了这些知识之后,我们有理由认为客户端程序会将初始值Words.FIRST, Words.SECOND, Words.THIRD编译进class文件,然后无论Words类是否被改变,客户端都会打印the null set。
运行了程序,你会发现它打印的是the chemistry set。
关键是null不是一个编译期常量表达式