Java常量类,在修改静态常量的值之后,不生效
修改一个常量类中的静态常量值,然后把常量类的class文件上传到服务器后并没有生效,多次重启服务,最后查询了相关资料,使用GUI反编译工具反编译查看编译后源码,终于找到问题所在:单纯的修改静态常量是没用的,还要重新编译所有引用静态变量的类(或把这些类重新上传服务器),不然不会生效。这里就牵扯到Java虚拟机编译机制:在Java文件中,指向编译时static final的静态常量, 会在运行....
修改一个常量类中的静态常量值,然后把常量类的class文件上传到服务器后并没有生效,多次重启服务,最后查询了相关资料,使用GUI反编译工具反编译查看编译后源码,终于找到问题所在:
单纯的修改静态常量是没用的,还要重新编译所有引用静态变量的类(或把这些类重新上传服务器),不然不会生效。
这里就牵扯到Java虚拟机编译机制:在Java文件中,指向编译时static final的静态常量, 会在运行时被解析为一个局部的常量值(也就是说静态常量在编译后,成为了常量,而不是原先的代码)。这对所有的基础数据类型(如int ,float等)和java.lang.String都适用。
请看下面一个实例:
程序中使用的各种常量用一个类Contants.java来统一管理。
public class Contants{
public static final String STR = "csyor.com";
//......
}
然后在某些逻辑代码段里使用了这些常量。这样做可以便于管理常量,避免了大量的magic number/text,在修改常量内容时只需改这一个类就行了。
import Contant;
public class SomeService {
public void doSome() {
// 这里应用了上一个类的静态常量Contants.STR
System.out.println(Contants.STR);
}
}
在上面的代码中,SomeService类使用了Contants.STR这个常量,表面上是通过Contants类取得的这个值,实际上在SomeService被编译后,其代码已经改变,如下:
import Contant;
public class SomeService {
public void doSome() {
// 这里把静态常量Contant.STR直接编译成为了一个常量"csyor.com"
System.out.println("csyor.com");
}
}
我们发现,这里面根本没有Contants类什么事,所以即使我们修改了Contants类中的常量,让STR = “www.csyor.com”,但是SomeService中依然会打印 “csyor.com” ,因为SomeService中的代码没有任何修改,在增量编译的情况下,它的class文件不会被重新编译。
那么说到这里可能会有人问:那为什么你在本地调试的好用呢?
主要是因为本地一般使用的IDE(集成开发环境)是可以自动编译的,而我们上传到服务器的时候一般只是上传自己更改过的java文件编译后的class文件(也就是包含静态常量的class),至于引用这个静态常量的其他类因为没有改动过所以不会上传,就出现了本地调试不会出现问题,但是在服务器上没有效果的情况。
明白了上面这些,问题就已经解决了,注意:不管是更换什么class文件,一定需要重启中间件容器。
解决方法一:单纯的修改静态变量STR是没用的,还要重新编译所有引用过静态变量STR的类(然后重新上传到服务器),不然不会生效,也就是说使用到这个常量的类都要重新编译。
解决方法二:去掉final
使用静态常量时一定要慎重,因为一旦修改它,就需要将整个项目中引用过该静态常量的地方重新编译替换。
更多推荐
所有评论(0)