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

在开篇之前,先补充一下《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(本质是无类型),那么结果就直接返回falseSystem.out.println(null instanceof String);// false。即使将null强转也还是个nullSystem.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)方法,而且确认它符合方法签名条件,由于编译器也爱“偷懒”,,所以程序会执行第一个方法。

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

期待遇上一位撑着油纸伞,结着忧愁丁香一样的姑娘;或者在春暖花开时,

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

相关文章:

你感兴趣的文章:

标签云: