将局部变量的作用域最小化
在方法的一开头就声明一个局部变量这样的做法是不正确的,请在第一次使用该变量的地方声明局部变量。
for循环优先于while循环,因为while循环将会在while循环体外声明局部变量,而for循环只会在循环体内声明局部变量,这样局部变量的作用域就限定在了循环体内。
for-each循环优先于传统的for循环
for-each不仅可以遍历数组、集合还可以遍历任何实现了Iterable接口的对象。
并且for-each会避免许多不必要的bug,它的遍历性能不比for循环差。
有3种情况不能使用for-each循环:
①如果遍历的是集合,需要调用remove方法就必须用for循环,因为for循环有显示的下标,而for-each循环没有。
②如果遍历的是数组,需要给数组赋值就必须使用for循环,因为给数组赋值需要显示的下标。
③平行迭代
如果需要精确的答案,请避免使用float和double
当使用float或者double类型的数值进行计算时,它并不能计算出我们想要的结果,比如
System.out.println(1-0.9);
它打印的值是0.09999999999999998!!!
有2种解决办法:
①使用BigDecimal类型计算,它会影响性能,但是它支持8种舍入模式。
BigDecimal a= new BigDecimal("1.00");
BigDecimal b=new BigDecimal(".9");
System.out.println(a.subtract(b));//a-b=0.10
System.out.println(a.add(b));//a+b=1.90
②使用int、long类型计算,int和long都是整数数值,所以要把计算值全部转化成整数在计算。
System.out.println(1*10-.9*10);//1.0
总结:
对于需要精确计算结果的请务必不要使用float和double!!!当我们不介意性能问题时,请使用BigDecimal,当我们介意性能问题,并且计算的数值不太大时请使用int和long类型,当数值不超过9位时请使用int类型,当数值超过9位但不超过18位时请使用long类型,当长度超过18位时只能使用BigDecimal类型。
基本数据类型优于封装数据类型
基本数据类型和封装数据类型的不同点
①基本数据类型只有值并且它们的值相同则用==比较就返回true,而封装数据类型可以拥有相同的值,但是它们本身比较却是不相同的。
②基本数据类型有功能完备的值,而封装数据类型可以是一个null值。
③基本数据类型的性能优于封装数据类型
针对以上第一点,请看下面的例子:
Comparator<Integer> com = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o1<o2?-1:(o1==o2?0:1);
}
};
System.out.println(com.compare(new Integer(12),new Integer(12)));
System.out.println(com.compare(128,128));
上面的程序打印按照程序的设计初衷应该都返回0,但是实际上都打印1!这是因为封装数据类型在进行大于、小于比较时会自动拆箱成基本数据类型,但是在用==比较时会并不会自动拆箱,因为==比较的是内存地址,所以new了2个新对象,它们一定是不想等的,所以打印1。我们都知道Integer有一个初始的默认的范围-128—127,在这个范围内赋值是不需要重新分配内存地址的,但是超过这个范围就需要在栈内存中重新分配地址,所以128和128是两个不同的对象所以打印1。想要解决这个问题只需要声明2个int类型的变量,将Integer的值赋给它们即可。
针对上面的第二点,请看下面的例子:
static Integer i;
public static void main(String[] args) {
if(i==10)
System.out.println("unbelievable");
}
当基本数据类型和封装数据类型混合使用时,一定是封装数据类型自动拆箱成基本数据类型,而这里的Integer i为null,所以在自动拆箱是会报出nullpointerexception的错误。解决方法就是用int类型代替Integer类型。
针对以上第三点,请看下面例子:
Long sum = 0L;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
sum+=i;
}
System.out.println(sum);
这个例子将会执行的非常慢,因为Long类型的变量需要重复拆箱、装箱的操作,非常占内存,解决方法是用long代替Long。
但也并不完全不使用封装数据类型,当集合中指定数据类型时必须使用封装数据类型,还有在调用反射的方法时必须使用封装数据类型,其他时候尽量用基本数据类型代替封装数据类型。
当心字符串连接的性能
String s = "abc"; s += "def";这2句代码将会创建2个对象,因为String是不可变的,所以在使用+=这种连接符时相当于重新创建一个对象进行赋值。请使用StringBuilder代替它。例如StringBuilder sb = new StringBuilder(); sb.append("abc");sb.append("def");
通过接口引用对象
请使用接口作为引用对象的类型,这样极大的提高代码的灵活性,这也是多态的表现(子类对象指向父类引用)。如果类没有合适的接口,请使用它的基类(可以是抽象类也可以是普通类)作为引用类型。
接口优先于反射机制
反射机制的缺点:
①丧失了编译时类型检查的好处,运行时才会报出不存在的类或者不可访问的方法。
②通过反射机制实例化一个对象的代码非常冗长。
③性能降低
谨慎使用本地方法
使用本地方法有很大的开销,并且使用不当可能破坏整个系统。
谨慎地进行优化
我们要设计好的程序,而不是快的程序。