建议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