编写高质量代码:改善Java程序的151个建议 --[26~36]
提防包装类型的null值
public static int testMethod(Listlist) { int count = 0; for (Integer i : list) { count += (i != null) ? i : 0; } return count; }复制代码
包装对象和拆箱对象可以自由转换,这不假,但是要剔除null值,null值并不能转换为基本类型。对于此问题,我们谨记一点:包装类型参与运算时,要做null值校验。
谨慎包装类型的大小比较
- i==j:在java中"=="是用来判断两个操作数是否有相等关系的,如果是基本类型则判断值是否相等,如果是对象则判断是否是一个对象的两个引用,也就是地址是否相等,这里很明显是两个对象,两个地址不可能相等。
- i>j 和 i<j:在Java中,">" 和 "<" 用来判断两个数字类型的大小关系,注意只能是数字类型的判断,对于Integer包装类型,是根据其intValue()方法的返回值(也就是其相应的基本类型)进行比较的(其它包装类型是根据相应的value值比较的,如doubleValue,floatValue等),那很显然,两者不肯能有大小关系的。
优先使用整型池
(1)、new产生的Integer对象
new声明的就是要生成一个新的对象,没二话,这是两个对象,地址肯定不等,比较结果为false。
(2)、装箱生成的对象
对于这一点,首先要说明的是装箱动作是通过valueOf方法实现的,也就是说后两个算法相同的,那结果肯定也是一样的,现在问题是:valueOf是如何生成对象的呢?我们来阅读以下Integer.valueOf的源码:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }复制代码
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low)); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }复制代码
cache是IntegerCache内部类的一个静态数组,容纳的是-128到127之间的Integer对象。通过valueOf产生包装对象时,如果int参数在-128到127之间,则直接从整型池中获得对象,不在该范围内的int类型则通过new生成包装对象。
不要随便设置随机种子
在Java中,随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个原则: 种子不同,产生不同的随机数 种子相同,即使实例不同也产生相同的随机数
import java.util.Random;public class Client30 { public static void main(String[] args) { Random r = new Random(); for(int i=1; i<=4; i++){ System.out.println("第"+i+"次:"+r.nextInt()); } }}复制代码
Random r = new Random(1000);复制代码
1000为随机种子,运行多次,虽然实例不同,但都会获得相同的四个随机数。 ####在接口中不要存在实现代码
public class Client31 { public static void main(String[] args) { //调用接口的实现 B.s.doSomeThing(); }}// 在接口中存在实现代码interface B { public static final S s = new S() { public void doSomeThing() { System.out.println("我在接口中实现了"); } };}// 被实现的接口interface S { public void doSomeThing();}复制代码
在B接口中声明了一个静态常量s,其值是一个匿名内部类(Anonymous Inner Class)的实例对象,就是该匿名内部类(当然,也可以不用匿名,直接在接口中是实现内部类也是允许的)实现了S接口。 ####静态变量一定要先声明后赋值 静态变量是在类初始化的时候首先被加载的,JVM会去查找类中所有的静态声明,然后分配空间,注意这时候只是完成了地址空间的分配,还没有赋值,之后JVM会根据类中静态赋值(包括静态类赋值和静态块赋值)的先后顺序来执行。对于程序来说,就是先声明了int类型的地址空间,并把地址传递给了i,然后按照类的先后顺序执行赋值操作,首先执行静态块中i = 100,接着执行 i = 1,那最后的结果就是 i =1了。
####不要覆写静态方法
避免在构造函数中初始化其它类
public class Client35 { public static void main(String[] args) { Son son = new Son(); son.doSomething(); }}// 父类class Father { public Father() { new Other(); }}// 相关类class Other { public Other() { new Son(); }}// 子类class Son extends Father { public void doSomething() { System.out.println("Hi, show me Something!"); }}复制代码
造成构造方法循环调用
原文链接:https://www.cnblogs.com/androidsuperman/p/9358122.html8122