网站导航栏制作,杭州产品设计公司有哪些,企业网站系统的设计与开发教程,网站流量如何提高本文先讲述装箱和拆箱最基本的东西#xff0c;再来看一下面试笔试中经常遇到的与装箱、拆箱相关的问题。
目录#xff1a; 装箱和拆箱概念 装箱和拆箱是如何实现的 面试中相关的问题
装箱和拆箱概念
Java为每种基本数据类型都提供了对应的包装器类型#xff0c;至于为…本文先讲述装箱和拆箱最基本的东西再来看一下面试笔试中经常遇到的与装箱、拆箱相关的问题。
目录 装箱和拆箱概念 装箱和拆箱是如何实现的 面试中相关的问题
装箱和拆箱概念
Java为每种基本数据类型都提供了对应的包装器类型至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述有兴趣的朋友可以查阅相关资料。在Java SE5之前如果要生成一个数值为10的Integer对象必须这样进行
Integer i new Integer(10);
而在从Java SE5开始就提供了自动装箱的特性如果要生成一个数值为10的Integer对象只需要这样就可以了
Integer i 10;
这个过程中会自动根据数值创建对应的 Integer对象这就是装箱。
那什么是拆箱呢顾名思义跟装箱对应就是自动将包装器类型转换为基本数据类型
Integer i 10; //装箱
int n i; //拆箱
简单一点说装箱就是 自动将基本数据类型转换为包装器类型拆箱就是 自动将包装器类型转换为基本数据类型。
下表是基本数据类型对应的包装器类型 装箱和拆箱是如何实现的
我们就以Interger类为例下面看一段代码
public class Main{public static void main(String[] args){Integer i 10;int n i;}
}
反编译class文件之后得到如下内容 从反编译得到的字节码内容可以看出在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法。
其他的也类似比如Double、Character不相信的朋友可以自己手动尝试一下。
因此可以用一句话总结装箱和拆箱的实现过程
装箱过程是通过调用包装器的valueOf方法实现的而拆箱过程是通过调用包装器的 xxxValue方法实现的。xxx代表对应的基本数据类型。
面试中相关的问题
下面列举一些常见的与装箱/拆箱有关的面试题。
1.下面这段代码的输出结果是什么
public class Main {public static void main(String[] args) {Integer i1 100;Integer i2 100;Integer i3 200;Integer i4 200;System.out.println(i1i2);System.out.println(i3i4);}
}
输出结果
true
false
为什么会出现这样的结果输出结果表明i1和i2指向的是同一个对象而i3和i4指向的是不同的对象。此时只需一看源码便知究竟下面这段代码是Integer的valueOf方法的具体实现
public static Integer valueOf(int i) {if(i -128 i IntegerCache.high)return IntegerCache.cache[i 128];elsereturn new Integer(i);
}
而其中IntegerCache类的实现为
private static class IntegerCache {static final int high;static final Integer cache[];
static {final int low -128;
// high value may be configured by propertyint h 127;if (integerCacheHighPropValue ! null) {// Use Long.decode here to avoid invoking methods that// require Integers autoboxing cache to be initializedint i Long.decode(integerCacheHighPropValue).intValue();i Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh Math.min(i, Integer.MAX_VALUE - -low);}high h;
cache new Integer[(high - low) 1];int j low;for(int k 0; k cache.length; k)cache[k] new Integer(j);}
private IntegerCache() {}
}
从这2段代码可以看出在通过valueOf方法创建Integer对象的时候如果数值在[-128,127]之间便返回指向IntegerCache.cache中已经存在的对象的引用否则创建一个新的Integer对象。
上面的代码中i1和i2的数值为100因此会直接从cache中取已经存在的对象所以i1和i2指向的是同一个对象而i3和i4则是分别指向不同的对象。
2.下面这段代码的输出结果是什么?
public class Main {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(i1i2);System.out.println(i3i4);}
}
输出结果
false
false
在这里只解释一下为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单在某个范围内的整型数值的个数是有限的而浮点数却不是。
注意 Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。 Double、Float的valueOf方法的实现是类似的。
3.下面这段代码输出结果是什么
public class Main {public static void main(String[] args) {Boolean i1 false;Boolean i2 false;Boolean i3 true;Boolean i4 true;System.out.println(i1i2);System.out.println(i3i4);}
}
输出结果
true
true
至于为什么是这个结果同样地看了Boolean类的源码也会一目了然。下面是Boolean的valueOf方法的具体实现
public static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE);
}
而其中的 TRUE 和FALSE又是什么呢在Boolean中定义了2个静态成员属性
public static final Boolean TRUE new Boolean(true);
/**
* The codeBoolean/code object corresponding to the primitive
* value codefalse/code.
*/
public static final Boolean FALSE new Boolean(false);
至此大家应该明白了为何上面输出的结果都是true了。
4.谈谈Integer i new Integer(xxx)和Integer i xxx;这两种方式的区别。
当然这个题目属于比较宽泛类型的。但是要点一定要答上我总结一下主要有以下这两点区别 1第一种方式不会触发自动装箱的过程而第二种方式会触发 2在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况注意这并不是绝对的。
5.下面程序的输出结果是什么
public class Main {public static void main(String[] args) {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(cd); //trueSystem.out.println(ef); //falseSystem.out.println(c(ab)); //trueSystem.out.println(c.equals(ab)); //trueSystem.out.println(g(ab));//trueSystem.out.println(g.equals(ab));//falseSystem.out.println(g.equals(ah));//true}
}
输出结果
true
false
true
true
true
false
true
当 运算符的两个操作数都是包装器类型的引用则是比较指向的是否是同一个对象而如果其中有一个操作数是表达式即包含算术运算则比较的是数值即会触发自动拆箱的过程。另外对于包装器类型equals方法并不会进行类型转换。明白了这2点之后上面的输出结果便一目了然
第一个和第二个输出结果没有什么疑问。第三句由于 ab包含了算术运算因此会触发自动拆箱过程会调用intValue方法因此它们比较的是数值是否相等。而对于c.equals(ab)会先触发自动拆箱过程再触发自动装箱过程也就是说ab会先各自调用intValue方法得到了加法运算后的数值之后便调用Integer.valueOf方法再进行equals比较。同理对于后面的也是这样不过要注意倒数第二个和最后一个输出的结果如果数值是int类型的装箱过程调用的是Integer.valueOf如果是long类型的装箱调用的Long.valueOf方法。