如果之前学习过自动装箱的知识,可以先做下面几道面试题,帮助我们发现自己的知识盲点。如果你没有了解过自动装箱,可以先跳到后面阅读知识点总结部分,再回来做题。
public void test() { //1 int a = 100; Integer b = 100; System.out.println(a == b);// true //2 Integer c = 100; Integer d = 100; System.out.println(c == d);// true //3 c = 200; d = 200; System.out.println(c == d);// false } 复制代码
public static void main(String[] args) { Double i1 = 100.0; Double i2 = 100.0; Double i3 = 200.0; Double i4 = 200.0; System.out.println(i1==i2);//false System.out.println(i3==i4);//false } 复制代码
在这里解释一下为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单,因为在某个范围内的整型数值的个数是有限的,而浮点数却不是。也就是说, Double和Float的valueOf方法始终返回新对象 。
注意:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。Double、Float的valueOf方法的实现是类似的。
面试题三涉及的知识点在上面都介绍过了,先尝试一下不看答案的情况下,自己能全部回答正确吗。
Integer a=1; Integer b=2; Integer c=3; Integer d=3; Integer e=321; Integer f=321; Long g=3L; System.out.println(c==d); System.out.println(e==f); System.out.println(c==(a+b)); System.out.println(c.equals(a+b)); System.out.println(g==(a+b)); System.out.println(g.equals(a+b)); 复制代码
答案:
true false true true true false
以Float为例
自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,会 创建多余的对象 ,影响程序的性能。
Integer sum = 0; for(int i=1000; i<5000; i++){ sum+=i; } 复制代码
上面的代码 sum+=i
可以看成 sum = sum + i
,但是 +
这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其内部变化如下
int result = sum.intValue() + i; Integer sum = new Integer(result); 复制代码
由于我们这里声明的sum为Integer类型,在上面的循环中会创建将近4000个无用的Integer对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。
因为自动装箱会隐式地创建对象,像前面提到的那样,如果在一个循环体中,会创建无用的中间对象,这样会增加GC压力,拉低程序的性能。所以在写循环时一定要注意代码,避免引入不必要的自动装箱操作。