Java代码优化系列(一)开篇立碑

转载请注明出处: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)方法,而且确认它符合方法签名条件,由于编译器也爱“偷懒”,所以程序会执行第一个方法。

参考文献:《编写高质量代码》机械工业出版社



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。