代码中我们一般都使用一个类统一管理常量,例如:
public class AppConst {
public static final String STR_1 = "String1";
public static final String STR_2 = "String2";
......
}
这样我们在修改常量值的时候只用在这个类中修改即可,今天我遇到了一个很费解的问题,我在SpringMVC工程中需要需改一个常量值,因为SpringMVC工程的class文件众多,所以我偷懒只将修改后编译的AppConst class文件上传到服务器替换了,结果无论怎么调用常量对应的值都没有更新过来,通过反编译调用的class文件发现,使用常量的地方,已经被替换成常量的值,也就是说编译后常量的值“就地展开”,不是“动态引用”的,经过搜索发现如下内容:
静态常量(即用 static final
修饰的变量)是编译时常量,当一个class文件编译完毕,它内部使用到的所有常量的具体值就已经确定了,不能想当然地以为它在运行时并连接常量管理类之后才会以引用方式使用常量。
举个例子
import AppConst;
public class SomeService {
public void serviceJob1() {
System.out.println(AppConst.STR_1);
}
}
类SomeService使用了STR_1这个常量,表面上是通过AppConst类取得的这个值,实际上在SomeService被编译后,其代码其实变成了
import AppConst;
public class SomeService {
public void serviceJob1() {
System.out.println("String1");
}
}
通过上面的分析,要使常量修改后,其他引用的class也同步改过来,就必须将引用了这个常量的class重新编译后上传,这样才能同步修改。