前言:什么是装箱和拆箱?
自动根据数值创建对应的Integer对象,这就是装箱。
自动将包装器类型转换为基本数据类型,这就是拆箱。
1.问:如下程序运行结果是什么?
Longl1=128L;
Longl2=128L;
System.out.print(l1==l2)//1
System.out.print(l1==128L);//2
System.out.print(l3==l4);//3
System.out.print(l3==127L);//4
答:对于注释1的语句,Long包装类型常量cache为-128到127之间,所以l1和l2变量是两个对象,==比较的是对象的地址,所以打印为false。
对于注释2的语句,由于包装类型在表达式中且表达式中至少有一个不是包装类型,所以Longl1==128L中l1**自动拆箱退化为基本类型比较**,所以数值比较为true。
对于注释3的语句,Long包装类型-128到127之间的值维护在一个常量池中,所以l3和l4引用同一个对象,故打印true。
对于注释4的语句类似注释2语句,所以打印为true。
2.问:java是否存在使得语句i>j||i<=j结果为false的i、j值?
答:存在,**java的数值NaN代表notanumber,无法用于比较**,例如使**i=Double.NaN;j=i;**最后i==j的结果依旧为false,这是一道非常变态的题,巨坑,谁特么会这么用。
3.问:java1.5的自动装箱拆箱机制是编译特性还是虚拟机运行时特性?分别是怎么实现的?
答:java1.5开始的自动装箱拆箱机制其实是编译时自动完成替换的,装箱阶段自动替换为了valueOf方法,拆箱阶段自动替换为了xxxValue方法。
对于Integer、Short、Byte、Character、Long类型的valueOf方法,参数如果是-128~127之间的值会直接返回内部缓存池中已经存在对象的引用,参数是其他范围值则返回新建对象;
而Double、Float类型与Integer类型类似,一样会调用Double、Float的valueOf方法,但是不管传入的参数值是多少都会new一个对象来表达该数值,因为在某个范围内的整型数值的个数是有限的,而浮点数却不是。
4.问:下面是一组java包装类型、自动拆箱、装箱的题目,请写出运行结果?
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//false
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
//在Boolean中定义了2个静态成员属性
Boolean i1 = false;
Boolean i2 = false;
Boolean i3 = true;
Boolean i4 = true;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//true
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c==d);//true 比较cache
System.out.println(e==f);//false 比较引用
System.out.println(c==(a+b));//true 比较值
System.out.println(c.equals(a+b));//true 比较值
System.out.println(g==(a+b));//true //比较值
System.out.println(g.equals(a+b));//false //比较引用(对于包装器类型,equals方法并不会进行类型转换)
System.out.println(g.equals(a+h));//true比较引用
Integer a = 444;
int b = 444;
System.out.println(a==b); //true 比较值
System.out.println(a.equals(b));//true比较值
答案解析:
对于两边都是包装类型的比较==比较的是引用,equals比较的是值。
对于两边有一边是表达式(包含算数运算)则==比较的是数值(自动触发拆箱过程),对于包装类型equals方法不会进行类型转换。
5.问:java语句Integeri=1;i+=1;
做了哪些事情?
首先 Integer i = 1; 做了自动装箱(使用 Integer.valueOf() 方法将 int 装箱为 Integer 类型),接着 i += 1; 先将 Integer 类型的 i 自动拆箱成 int(使用Integer.intValue() 方法将 Integer 拆箱为 int),完成加法运行之后的 i 再装箱成 Integer 类型。
6.问:下面程序的运行结果是什么?
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);//false
System.out.println(i1.equals(i2));//true
注意,new Integer(xxx)这种创建对象的方法不是自动装箱,没有用到cache,因此i1 == i2是false。
7.谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。
1)第一种方式不会触发自动装箱的过程;而第二种方式会触发。
2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。
摘自微信公众号:码农每日一题