java代码优化(七)——通用程序设计

将局部变量的作用域最小化

在方法的一开头就声明一个局部变量这样的做法是不正确的,请在第一次使用该变量的地方声明局部变量。

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类型的数值进行计算时,它并不能计算出我们想要的结果,比如

扫描二维码关注公众号,回复: 5277472 查看本文章
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");

通过接口引用对象

请使用接口作为引用对象的类型,这样极大的提高代码的灵活性,这也是多态的表现(子类对象指向父类引用)。如果类没有合适的接口,请使用它的基类(可以是抽象类也可以是普通类)作为引用类型。

接口优先于反射机制

反射机制的缺点:

①丧失了编译时类型检查的好处,运行时才会报出不存在的类或者不可访问的方法。

②通过反射机制实例化一个对象的代码非常冗长。

③性能降低

谨慎使用本地方法

使用本地方法有很大的开销,并且使用不当可能破坏整个系统。

谨慎地进行优化

我们要设计好的程序,而不是快的程序。

遵守普遍接受的命名规范

猜你喜欢

转载自blog.csdn.net/ZixiangLi/article/details/86236385
今日推荐