java开发150个建议(15)


关于常量接口(类)我们开看一个例子,首先定义一个常量类:
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工具中完成的,下面暂时回溯到原始时代,也就是回归到用记事本编写代码的年代,然后看看会发生什么事情(为什么要如此,下面会给出答案)
修改常量类,人类的寿命极限增加了,最大活到180,代码如下:
public class Constant {//定义人类寿命极限public static final int MAX_AGE=180;}
然后重新编译,javac ,编译完成后执行:java ,大家猜猜输出的年龄是多少?
输出的结果是:"人类的寿命极限是150",竟然没有改成180,太奇怪了,这是为何?
原因是:对于final修饰的基本类型和类型,编译器会认为它是稳定态的( )所以在编译时就直接把值编译到字节码中了,避免了在运行期引用(Run-time ),以提高代码的执行效率 。对于我们的例子来说,类在编译时字节码中就写上了"150",这个常量,而不是一个地址引用,因此无论你后续怎么修改常量类,只要不重新编译类,输出还是照旧 。
对于final修饰的类(即非基本类型),编译器会认为它不是稳定态的( ),编译时建立的则是引用关系(该类型也叫作Soft Final) 。如果类引入的常量是一个类或实例,及时不重新编译也会输出最新值 。
千万不可小看了这点知识,细坑也能绊倒大象,比如在一个web项目中,开发人员修改了一个final类型的值(基本类型)考虑到重新发布的风险较大,或者是审批流程过于繁琐,反正是为了偷懒,于是直接采用替换class类文件的方式发布,替换完毕后应用服务器自动重启,然后简单测试一下,一切Ok,可运行几天后发现业务数据对不上,有的类(引用关系的类)使用了旧值,有的类(继承关系的类)使用的是新值,而且毫无头绪,让人一筹莫展,其实问题的根源就在于此 。
还有个小问题没有说明,我们的例子为什么不在IDE工具(比如)中运行呢?那是因为在IDE中设置了自动编译不能重现此问题,若修改了类,IDE工具会自动编译所有的引用类,"智能"化屏蔽了该问题,但潜在的风险其实仍然存在,我记得应该有个设置自动编译的入口,有兴趣大家可以自己尝试一下 。
回到顶部
建议21:用偶判断,不用奇判断
判断一个数是奇数还是偶数是小学里的基本知识,能够被2整除的整数是偶数,不能被2整除的数是奇数,这规则简单明了,还有什么可考虑的?好,我们来看一个例子,代码如下:
1 import java.util.Scanner;2 3 public class Client21 {4public static void main(String[] args) {5// 接收键盘输入参数6Scanner input = new Scanner(System.in);7System.out.println("输入多个数字判断奇偶:");8while (input.hasNextInt()) {9int i = input.nextInt();10String str = i + "-->" + (i % 2 == 1 ? "奇数" : "偶数");11System.out.println(str);12 13}14}15 }
输入多个数字,然后判断每个数字的奇偶性,不能被2整除的就是奇数,其它的都是偶数,完全是根据奇偶数的定义编写的程序,我们开看看打印的结果:
输入多个数字判断奇偶:1 2 0 -1 -2 1-->奇数 2-->偶数 0-->偶数 -1-->偶数 -2-->偶数
前三个还很靠谱,第四个参数-1怎么可能是偶数呢,这Java也太差劲了吧 。如此简单的计算也会出错!别忙着下结论,我们先来了解一下Java中的取余(%标识符)算法,模拟代码如下: