转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45506549
在开篇之前,先补充一下《Java学习系列》里面的instanceof关键字的使用及其陷阱。简要说明:instanceof是一个简单的二元操作符,它是用来判断一个对象是否为一个类的实例。只要instanceof左右操作数有继承或实现的关系,程序都是可以编译通过的。下面通过一个简单实例来说明一下instanceof关键字的使用及其陷阱:
class A<T> { public boolean isDateInstance(T t) { return t instanceof Date; } } public class InstanceofTest { public static void main(String[] args) { // true。一个String对象是Object实例(java中Object是所有类的父类) System.out.println("zhangsan" instanceof Object); // false。Object是父类,它的对象明显不是String类的实例 System.out.println(new Object() instanceof String); // true。一个String对象是String的实例 System.out.println(new String() instanceof String); // 编译不能通过。'a' 为一个char类型,即基本类型 // System.out.println('a' instanceof Character); // false。只要左操作数为null(本质是无类型),那么结果就直接返回false System.out.println(null instanceof String); // false。即使将null强转也还是个null System.out.println((String) null instanceof String); // 编译不能通过。因为Date和String并没有继承或实现关系 // System.out.println(new Date() instanceof String); // false。在编译成字节码时,T已经是Object类型了,由于传递了一个"lisi"实参字符串,所以T实际是String类型了。 System.out.println(new A().isDateInstance("lisi")); } }
【注意】instanceof只能用于对象的判断,不能用于基本类型的判断。
下面开始正式进入主题,先从一个自增的陷阱开始吧。
1)自增的陷阱
int num = 0; for (int i = 0; i < 100; i++) { num = num++; } System.out.println("num = " + num);
打印结果是什么呢?答案是0,为什么呢?先看看执行步骤吧,程序第一次循环时的详细步骤如下:JVM把num值(0)拷贝到临时变量区,然后num值加1,这是num的值为1,接着返回临时变量区的值,注意这个值是1没修改过,最后将返回值赋给num,此时num的值被重置为了0。简单说来就是int temp = num; num += 1; return temp;这3步。所以打印结果还是0,num始终保持着原来的状态。
优化:将num=num++; 修改为num++即可。
2)常量竟成变量?
大家想想,常量有可能成为变量吗?答案是有可能,只不过这种做法是不被认同的。
public static final int RAND_CONST = new Random().nextInt(); public static void main(String[] args) { // 通过打印几次,可以看到结果变了,也就是说常量在定义的时候就没有保证它的值运行期保持不变 System.out.println("常量变了吗?" + RAND_CONST); }
优化建议:务必常量的值在运行期保持不变,所以可以让RAND_CONST在定义时直接赋值写死。
3)“l” 你能看出这个字母是i的大写、数字1还是字母l的小写?
public static long l = 11;
优化:字母后缀l尽量大写L
4)三目运算符的类型不一致?
int i = 70; System.out.println(i < 100 ? 80 : 90.0);
打印结果出人意料,结果竟然为80.0,这是为什么呢?i<100确实为true,但由于最后一个操作数为90.0,是一个浮点数,这时编译器会将第二个操作数80转为80.0浮点数,统一结果类型,所以打印结果为80.0。
优化:90.0改为90
5)不要重载含有变长参数的方法
简要说明:变长参数必须是方法的最后一个参数,且一个方法不能定义多个变长参数。
public class Test01 { public static void fruitPrice(int price, int discount) { float realPrice = price * discount / 100.0F; System.out.println("非变长参数得出的结果:realPrice = " + realPrice); } public static void fruitPrice(int price, int... discounts) { float realPrice = price; for (int discount : discounts) { realPrice = price * discount / 100.0F; } System.out.println("变长参数得出的结果:realPrice = " + realPrice); } public static void main(String[] args) { fruitPrice(48888, 85); } }
打印结果是什么呢?答案是:非变长参数得出的结果:realPrice = 41554.8,也就是程序执行的是第一个方法,而没有执行变长参数方法,这是为什么呢?因为Java在编译时,首先会根据实参的数量和类型(这里是2个都是int类型的实参,注意没有转成int数组)来进行处理,也就是找到fruitPrice(int price, int discount)方法,而且确认它符合方法签名条件,由于编译器也爱“偷懒”,所以程序会执行第一个方法。
参考文献:《编写高质量代码》机械工业出版社