昆明java培训
达内昆明广州春城路

18487146383

热门课程

java培训:不要只替换一个类

  • 时间:2016-09-30
  • 发布:昆明Java培训
  • 来源:达内新闻

昆明达内Java培训的老师经常在系统中定义一个常量接口(或常量类),以囊括系统中所涉及的常量,从而简化代码,方便开发,在很多的开源项目中已经采用了类似的方法,比如在struts2中,org.apache.struts2.StrutsConstants就是一个常量类,它定义Struts框架中与配置有关的常量,而org.apache.struts2.StrutsConstants则是一个常量接口,其中定义了OGNL访问的关键字。

关于常量接口(类)我们开看一个例子,首先定义一个常量类:

public class Constant {

//定义人类寿命极限

public static final int MAX_AGE=150;

}

这是一个非常简单的常量类,定义了人类的最大年龄,我们引用这个常量,代码如下:

public class Client{

public static void main(String[] args) {

System.out.println("人类的寿命极限是:"+Constant.MAX_AGE);

}

}

运行结果easy,故省略。目前的代码是写在"智能型"IDE工具中完成的,下面暂时回溯到原始时代,也就是回归到用记事本编写代码的年代,然后看看会发生什么事情(为什么要如此,下面会给出答案)

修改常量Constant类,人类的寿命极限增加了,最大活到180,代码如下:

public class Constant {

//定义人类寿命极限

public static final int MAX_AGE=180;

}

然后重新编译,javac Constant,编译完成后执行:java Client,大家猜猜输出的年龄是多少?

输出的结果是:"人类的寿命极限是150",竟然没有改成180,太奇怪了,这是为何?

原因是:对于final修饰的基本类型和String类型,编译器会认为它是稳定态的(Immutable Status)所以在编译时就直接把值编译到字节码中了,避免了在运行期引用(Run-time Reference),以提高代码的执行效率。对于我们的例子来说,Client类在编译时字节码中就写上了"150",这个常量,而不是一个地址引用,因此无论你后续怎么修改常量类,只要不重新编译Client类,输出还是照旧。

对于final修饰的类(即非基本类型),编译器会认为它不是稳定态的(Mutable Status),编译时建立的则是引用关系(该类型也叫作Soft Final)。如果Client类引入的常量是一个类或实例,及时不重新编译也会输出最新值。

千万不可小看了这点知识,细坑也能绊倒大象,比如在一个web项目中,开发人员修改了一个final类型的值(基本类型)考虑到重新发布的风险较大,或者是审批流程过于繁琐,反正是为了偷懒,于是直接采用替换class类文件的方式发布,替换完毕后应用服务器自动重启,然后简单测试一下,一切Ok,可运行几天后发现业务数据对不上,有的类(引用关系的类)使用了旧值,有的类(继承关系的类)使用的是新值,而且毫无头绪,让人一筹莫展,其实问题的根源就在于此。

还有个小问题没有说明,我们的例子为什么不在IDE工具(比如Eclipse)中运行呢?那是因为在IDE中设置了自动编译不能重现此问题,若修改了Constant类,IDE工具会自动编译所有的引用类,"智能"化屏蔽了该问题,但潜在的风险其实仍然存在,我记得Eclipse应该有个设置自动编译的入口,有兴趣大家可以自己尝试一下。

昆明达内Java培训的老师提醒大家注意:发布应用系统时禁止使用类文件替换方式,整体WAR包发布才是万全之策。但我觉得应特殊情况特殊对待,并不可以偏概全,大家以为呢?

上一篇:java中断言绝对不是鸡肋
下一篇:用偶判断,不用奇判断

应届生来达内学Java技术,三年后以40w高薪入职大众点评

昆明达内java培训教你如何选择一门编程语言

阿里送好礼,java开发人员的福音来了

昆明达内java培训通知你下一年的八大趋势

选择城市和中心
贵州省

广西省

海南省

扫一扫

了解更多干货