目录
前言
一.基本数据类型与包装类的对应关系:
二.包装类基本介绍:
1.为何引入包装类:
2.自动装箱与拆箱
1)隐式拆装箱:
2)显示拆装箱:
三.面试常问:
1.以下代码结果为什么不同?
2.浅谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别:
3.综合考察:
总结
Hellow!大家好,我是Node_Hao!今天给大家带来的是java包装类中的自动装箱与拆箱,虽然这不是一个很复杂的知识点,但其中的部分细节却是面试官经常问到的,希望这篇文章能带给你启发!
基本数据类型 | 包装类 |
---|---|
byte |
Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
由以上对应关系我们可以看出,基本数据类型的包装类,除了Integer和Character其余都是首字母大写.
初学包装类我们都非常疑惑,既然已经有了基本数据类型,为什么需要包装类?其实,随着我们对java面向对象的理解不断深入,我们会发现在万物皆对象的java语言中,其基本数据类型居然不是面向对象的,这不仅给类型之间的转化带来了很多麻烦,在基本数据类型的基础上也很难有更多的操作,为了解决这类问题在JDK1.5引入了两个功能:1.自动装箱 2.自动拆箱.
- 自动装箱:当我们把基本数据类型赋值给引用类型时,系统会将它自动包装成所需的实例对象,这样基本数据类型就达到了面向对象的效果.
- 自动拆箱:当我们需要基本数据类型但此时传入的是包装类型,系统会自动拆箱,把包装类的值剥离出来.
public static void main4(String[] args) {
Integer a = 123;//装箱
int b = a;//拆箱[隐式的]
}
为什么叫隐式呢?我们来看反编译:
通过反编译我们发现,在执行以上代码的过程中,编译器自动调用了Integer.valueof()方法装箱, intValue()方法拆箱.
Integer a2 = Integer.valueOf(123);//显示装箱
int b2 = a2.intValue();//显示拆箱
通过以上代码我们可以发现,装箱与拆箱的过程我们都可以看到,所以叫显示拆装箱.
通过前面知识我们可知给Integer赋值相当于隐式装箱,系统会自动调用Integer.valueof()方法.所以我们只需要查看Integer.valueof()方法的原码即可.
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
cache为缓存的意思,所以我们推测Integer.valueof()方法的返回值有一定的范围,那么这个范围是多大呢?我们可以查看low和high的原码.
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
}
由此我们明白了,Integer.valueof()方法的底层是一个缓存数组,数组的大小范围是-128到127,如果我们输入的元素恰好在这个范围,valueof()方法便会指向cache数组中存在的引用,否则会创建一个新的Integer对象,指向的地址不同那么值自然也就不同了.
注意:除了Double和Float类型的valueof()方法外,其他基本类型的valueof()方法实现过程类似.这是因为浮点数的存储相较于其他类型会更加的复杂,我们可以简单观察一下源码. 感兴趣的读者下来可以深入了解一下,这里不过多讲述.
据了解Integer i = new Integer(xxx)这个方法已经过时,新一点的编译器可能无法通过编译.这恰好体现了new Integer(xxx)的不足之处:
1.new Integer(xxx)不会触发自动装箱机制,而第Integer i =xxx会.
2.执行效率上Integer i =xxx会更快.
public static void main(String args[])
{
Integer a = Integer.valueOf(1);
Integer b = Integer.valueOf(2);
Integer c = Integer.valueOf(3);
Integer d = Integer.valueOf(3);
Integer e = Integer.valueOf(321);
Integer f = Integer.valueOf(321);
Long g = Long.valueOf(3L);
Long h = Long.valueOf(2L);
System.out.println(c == d);
System.out.println(e == f);
System.out.println(c.intValue() == a.intValue() + b.intValue());
System.out.println(c.equals(Integer.valueOf(a.intValue() + b.intValue())));
System.out.println(g.longValue() == (long)(a.intValue() + b.intValue()));
System.out.println(g.equals(Integer.valueOf(a.intValue() + b.intValue())));
System.out.println(g.equals(Long.valueOf((long)a.intValue() + h.longValue())));
}
第一个和第二个之前已经讲过,是valueof()方法的范围问题,这里不过多赘述.第三个算数运算会触发自动拆箱Integer.valueof()方法,所以比较的是数组大小.第四个括号中的算数运算会先触发自动拆箱机制,之后又触发自动装箱机制,由于在cache数组的范围之内,所以为true.第五个也是同样的原理,第六个和第七个主要考察Long.valueof()的自动装箱类型只能和自己类型的比较.
以上就是深度剖析自动装箱与拆箱的全部内容了,如果我的总结对你有所启发和帮助,码字不易,麻烦给个三连哦!