建议21:用偶判断,不用奇判断
根据奇数判断奇偶性:i%2==1 ? "奇数":"偶数"
根据偶数判断奇偶性:i%2==0 ? "偶数":"奇数"
Java中的取余(%标示符)算法,模拟代码如下:
//模拟取余计算,dividend被除数,divisor除数
public static int remainder(int divident, int divisor){
return divident - dividend / divisor * divisor;
}
所以,如果根据奇数判断奇偶性时,当输入为-1时,计算结果为偶数。
因此,Java在判断奇偶性的时候要用偶判断。
建议22:用整数类型处理货币
system.out.println(10.00-9.60);
输出结果是:0.40000000000036
这是因为在计算机中浮点数有可能(注意有可能)是不准确的,它只是无限接近准确值,而不能完全精确。为什么会如此呢?这是由浮点数的存储规则所决定的,十进制小数是通过“乘2取整,顺序排列”法转换成二进制小数的。
0.4这个不能使用二进制准确的表示,在二进制数世界里它是一个无限循环的小数,就好比在十进制世界里没有办法准确表示1/3。
解决这种问题有两个方法:
(1)使用BigDecimal
(2)使用整形(例如先扩大100倍转变为整形,然后进行运算,然后再缩小100倍)
建议23:不要让类型默默转换
pubic static final LIGHT_SPEED = 30 * 10000 * 1000;
long dis2 = LIGHT_SPEED * 60 * 8;
输出dis2的结果为-2028888064
虽然声明了dis2为long型,但是仍然出现负值是因为Java是先运算然后进行类型转换的。所以因为三个乘数都是int型,三者相乘仍然是int型,但是已经超过int的最大值,所以就变成了负值。
这种问题的解决办法是将乘数转换成long型(加一个“L”)
long dis2 = LIGHT_SPEED * 60L * 8;
还没超过int范围的时候就已经转换为long型,在实际开发中,更通用的做法是主动声明式类型转化(注意不是强制类型转换),代码如下:
long dis2 = 1L * LIGHT_SPEED * 60 * 8;
基本类型转换时,使用主动方式减少不必要的Bug。
建议24:边界,边界,还是边界
int cur = 1000;
int limit = 2000;
int order = input.nextInt();
boolean bl = (order+cur) 其中order为客户端输入的值,当order输入2147483647时,bl的值为true。 数字越界使检验条件失败。 建议25:不要让四舍五入亏了一方 使用BigDecimal类,并且采购setScale方法设置精度。 目前Java支持以下七种舍入方式: 1)ROUND_UP:远离0方向舍入。(只要舍弃位非0即进位) 2)ROUND_DOWN:趋向0方向舍入。(所有的位都舍弃) 3)ROUND_CEILING:向正无穷方向舍入。(正数类似于ROUND_UP ,负数类似ROUND_DOWN ) 4)ROUND_FLOOR:想负无穷方向舍入。(与ROUND_CEILING 相反) 5)HALF_UP:最近数字舍入(5进)(即通常所说的四舍五入) 6)HALF_DOWN:类似HALF_UP,但是5不进位。 7)HALF_EVEN:银行家算法 银行家算法规则: 》舍弃位的数值小于5时,直接舍弃; 》舍弃位的数值等于6时,进位后舍去; 》舍弃位的数值等于5时,分两种情况:5后面还有其他数字(非零),则进位后舍去;若5后面是0(即5是最后一个数字),则根据5前一位数的奇偶性来判断是否需要进位,技术进位,偶数舍去。 总结成一句话:四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。 建议26:提防包装类型的null值 包装类型参与运算时,要做null值校验。 建议27:谨慎包装类型的大小比较 包装类型比较大小的时候用compareTo方法进行比较。 ==运算符比较的是基本类型是否相等,对于对象则是判断的两个对象的引用地址是否相等。 建议28:优先使用整型池 int ii = input.nextInt(); Integer i = new Integer(ii); Integer j = new Integer(ii); boolean a = i==j i=ii; j=ii; boolean b = i==j; i = Integer.valueOf(ii); j = Integer.valueOf(ii); boolean c = i==j; 当ii的输入为127时,a、b、c的值分别是:false、true、true 当ii的输入为128时,a、b、c的值分别是:false、false、false (1)new产生包装对象,地址不同,所以不相等。 (2)装箱动作是通过valueOf方法实现的,也就是说后两个比较中的算法一样。 Integer.valueOf的代码实现: public static Integer valueOf(int i){ final int offset = 128; if(i>=-128 && i<=127){ // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); } 说明在装箱时,如果是-128到127之间的int类型转换为Integer对象,则直接从cache数组里获得。 cache数组代码如下: public static Integer cache[] = new Integer[-(-128) + 127 + 1]; static{ for(int i = 0; i < cache.length; i++){ cache[i] = new Integer(i-128); } } cache是IntegerCache内部类的一个静态数组,容纳的是-128到127之间的Integer对象。通过valueOf产生包装对象时,若干参数在-128到127之间,则直接从整型池中获得对象,不在该范围内的int类型通过new 生成包装对象。 通过包装类的valueOf生成包装实例可以显著提高空间和时间性能。 建议29:优先选择基本类型 Java5之后实现了包装类型与基本类型之间的自动转换。但无论是从安全性、性能和稳定性方面来说,基本类型都是首选方案。 自动装箱有一个重要原则:基本类型可以先加宽,在转变成宽类型的包装类型,但不能直接转变成宽类型的包装类型。 建议30:不要随便设置随机种子 Random random = new Random(); for(int i=1;i<4;i++){ System.out.println("第"+i+"次:"+random.nextInt()); } 以上程序中输出随机数,三个随机数都不同,而且运行多次,每次的结果都是不同的。 但如果把random的构造使用随机数种子的方法: Random random = new Random(10000); 则每次说出的三个都是同样的三个随机数。 此时随机数的产生取决于种子: 》种子不同,产生的随机数不同。 》种子相同,即使实例不同也产生相同的随机数。 Random类的默认种子是System.nanoTime()的返回值(JDK1.5版本以前默认的种子是System.currentTimeMillis()的返回值) 因为默认的种子是不固定的,所以产生的随机数也不同。 因此,若非必要,不要设置随机数种子。 欢迎关注公众号: 零点小时光 lingdianxiaoshiguang