1700440024
1700440025
}
1700440026
1700440027
}
1700440028
1700440029
运行的结果非常简单(结果省略)。目前的代码编写都是在“智能型”IDE工具中完成的,下面我们暂时回溯到原始时代,也就是回归到用记事本编写代码的年代,然后看看会发生什么奇妙事情(为什么要如此,稍后会给出答案)。
1700440030
1700440031
修改常量Constant类,人类的寿命增加了,最大能活到180岁,代码如下:
1700440032
1700440033
public class Constant{
1700440034
1700440035
//定义人类寿命极限
1700440036
1700440037
public fnal static int MAX_AGE=180;
1700440038
1700440039
}
1700440040
1700440041
然后重新编译:javac Constant,编译完成后执行:java Client,大家想看看输出的极限年龄是多少岁吗?
1700440042
1700440043
输出的结果是:“人类寿命极限是:150”,竟然没有改变为180,太奇怪了,这是为何?
1700440044
1700440045
原因是:对于final修饰的基本类型和String类型,编译器会认为它是稳定态(Immutable Status),所以在编译时就直接把值编译到字节码中了,避免了在运行期引用(Run-time Reference),以提高代码的执行效率。针对我们的例子来说,Client类在编译时,字节码中就写上了“150”这个常量,而不是一个地址引用,因此无论你后续怎么修改常量类,只要不重新编译Client类,输出还是照旧。
1700440046
1700440047
而对于final修饰的类(即非基本类型),编译器认为它是不稳定态(Mutable Status),在编译时建立的则是引用关系(该类型也叫做Soft Final),如果Client类引入的常量是一个类或实例,即使不重新编译也会输出最新值。
1700440048
1700440049
千万不可小看了这点知识,细坑也能绊倒大象,比如在一个Web项目中,开发人员修改一个final类型的值(基本类型),考虑到重新发布风险较大,或者是时间较长,或者是审批流程过于繁琐,反正是为了偷懒,于是直接采用替换class类文件的方式发布。替换完毕后应用服务器自动重启,然后简单测试一下(比如本类引用final类型的常量),一切OK。可运行几天后发现业务数据对不上,有的类(引用关系的类)使用了旧值,有的类(继承关系的类)使用的是新值,而且毫无头绪,让人一筹莫展,其实问题的根源就在于此。
1700440050
1700440051
恩,还有个小问题没有说明,我们的例子为什么不在IDE工具(比如Eclipse)中运行呢?那是因为在IDE中不能重现该问题,若修改了Constant类,IDE工具会自动编译所有的引用类,“智能”化屏蔽了该问题,但潜在的风险其实仍然存在。
1700440052
1700440053
注意 发布应用系统时禁止使用类文件替换方式,整体WAR包发布才是万全之策。
1700440054
1700440055
1700440056
1700440057
1700440059
编写高质量代码:改善Java程序的151个建议 第2章 基本类型
1700440060
1700440061
不积跬步,无以至千里;
1700440062
1700440063
不积小流,无以成江海。
1700440064
1700440065
——荀子《劝学篇》
1700440066
1700440067
Java中的基本数据类型(Primitive Data Types)有8个:byte、char、short、int、long、float、double、boolean,它们是Java最基本的单元,我们的每一段程序中都有它们的身影,但我们对如此熟悉的“伙伴”又了解多少呢?
1700440068
1700440069
积少成多,积土成山,本章我们就来一探这最基本的8个数据类型。
1700440070
1700440071
1700440072
1700440073
[
上一页 ]
[ :1.700440024e+09 ]
[
下一页 ]