Java类更改常量后如何编译才能生效
2016-12-01 10:28
309 查看
多年以后又遇到了此问题,居然一时未想起曾经的原因,特备注。
最近一个Java项目中需要修改一个静态常量的值,本地修改编译以后调试正常,然后把对应的entity类的class文件上传到服务器对应的目录以后系统依旧我行我素,各种清除缓存,各种重启,最后查询了相关资料,使用GUI反编译工具反编译查看编译后源码,终于找到问题所在:
单纯的修改静态变量是没用的,还要重新编译所有引用静态变量的类,不然不会生效的。
这里就牵扯到Java虚拟机编译机制:在Java文件中,指向编译时static
final的静态常量,
会被在运行时解析为一个局部的常量值(也就是说静态常量在编译后,成为了常量,而不是原先的代码)。这对所有的基础数据类型(就像int
,float等)和java.lang.String都适用。
请看下面一个实例:程序中使用的各种常量用一个类Contant.java来统一管理。
public class Contant{
public static final String STR = "csyor.com";
//......
}
然后在某些逻辑代码段里使用了这些常量。这样做可以便于管理常量,避免了大量的magic number/text,在修改常量内容时只需改这一个类就行了。
import Contant;
public class SomeService {
public void doSome() {
//这里应用了上一个类的静态常量Contant.STR
System.out.println(Contant.STR);
}
}
类SomeService使用了Contant.STR这个常量,表面上是通过Contant类取得的这个值,实际上在SomeService被编译后,其代码已经改变为
import Contant;
public class SomeService {
public void doSome() {
//这里把静态常量Contant.STR直接编译成为了一个常量"csyor.com"
System.out.println("csyor.com");
}
}
这里面根本没有Contant类什么事,所以你即使修改了Contant类的相关常量,令STR = “www.csyor.com”,SomeService依然会打印 “csyor.com” ,因为SomeService的代码没有任何修改,在增量编译的情况下,它的class文件不会被重新编译。
那么说到这里可能会有人问:那为什么你在本地调试的好用呢?
主要是因为本地一般使用的IDE(集成开发环境)是可以自动编译的,而我们上传到服务器的时候一般只是上传自己更改过的java文件编译后的class文件(也就是包含静态常量的class),至于引用这个静态常量的其他类因为没有改动过所以不会上传,就出现了本地调试不会出现问题,但是在服务器上没有效果的情况。
明白了上面这些,我已经解决了问题,你应该也能知道怎么去解决了吧!当然,不管是更换什么class文件,一定需要重启中间件容器。
最近一个Java项目中需要修改一个静态常量的值,本地修改编译以后调试正常,然后把对应的entity类的class文件上传到服务器对应的目录以后系统依旧我行我素,各种清除缓存,各种重启,最后查询了相关资料,使用GUI反编译工具反编译查看编译后源码,终于找到问题所在:
单纯的修改静态变量是没用的,还要重新编译所有引用静态变量的类,不然不会生效的。
这里就牵扯到Java虚拟机编译机制:在Java文件中,指向编译时static
final的静态常量,
会被在运行时解析为一个局部的常量值(也就是说静态常量在编译后,成为了常量,而不是原先的代码)。这对所有的基础数据类型(就像int
,float等)和java.lang.String都适用。
请看下面一个实例:程序中使用的各种常量用一个类Contant.java来统一管理。
public class Contant{
public static final String STR = "csyor.com";
//......
}
然后在某些逻辑代码段里使用了这些常量。这样做可以便于管理常量,避免了大量的magic number/text,在修改常量内容时只需改这一个类就行了。
import Contant;
public class SomeService {
public void doSome() {
//这里应用了上一个类的静态常量Contant.STR
System.out.println(Contant.STR);
}
}
类SomeService使用了Contant.STR这个常量,表面上是通过Contant类取得的这个值,实际上在SomeService被编译后,其代码已经改变为
import Contant;
public class SomeService {
public void doSome() {
//这里把静态常量Contant.STR直接编译成为了一个常量"csyor.com"
System.out.println("csyor.com");
}
}
这里面根本没有Contant类什么事,所以你即使修改了Contant类的相关常量,令STR = “www.csyor.com”,SomeService依然会打印 “csyor.com” ,因为SomeService的代码没有任何修改,在增量编译的情况下,它的class文件不会被重新编译。
那么说到这里可能会有人问:那为什么你在本地调试的好用呢?
主要是因为本地一般使用的IDE(集成开发环境)是可以自动编译的,而我们上传到服务器的时候一般只是上传自己更改过的java文件编译后的class文件(也就是包含静态常量的class),至于引用这个静态常量的其他类因为没有改动过所以不会上传,就出现了本地调试不会出现问题,但是在服务器上没有效果的情况。
明白了上面这些,我已经解决了问题,你应该也能知道怎么去解决了吧!当然,不管是更换什么class文件,一定需要重启中间件容器。
相关文章推荐
- Java类更改常量后编译不生效
- editplus如何才能编译java语言
- Java类更改常量后编译不生效
- 如何保护Java程序 防止Java反编译
- 如何在Eclipse 3.3上安装jadclipse[java的反编译工具]
- JAVA中的JTextField 输入框,如何才能把他设置成透明的?
- 不修改 GridView的HeaderText,其中数据库中的头标题是:custName,custId.这样的字符同样显示在GridView中,应该如何更改才能让GridView的头一行显示:姓名,编号而不是显示custName,custId
- 更改logrotate配置后,怎么样才能使其生效????
- 如何更改java应用程序标题栏默认图标
- 不用ide编译java程序时如何调用jar包
- C++中在多个编译单元中如何定义常量
- 如何将.class文件转换成.java文件——JAVA反编译工具总结
- 如何编译及运行java
- 如何使用cmd编译java文件
- Java中如何由枚举常量的ordinal值获得枚举常量对象
- 在Myeclipse中是如何编译java文件的?
- 我刚刚学习java请问各位高手应该如何才能学好
- JAVA基础:如何才能成为Java开发高手
- 如何将java中class文件反编译成java文件
- Java中如何由枚举常量的ordinal值获得枚举常量对象