[Java]深度剖析自动装箱与拆箱

发布于:2023-02-09 ⋅ 阅读:(461) ⋅ 点赞:(0)

目录

前言

一.基本数据类型与包装类的对应关系:

二.包装类基本介绍:

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

        由以上对应关系我们可以看出,基本数据类型的包装类,除了IntegerCharacter余都是首字母大写.

二.包装类基本介绍:

1.为何引入包装类:

        初学包装类我们都非常疑惑,既然已经有了基本数据类型,为什么需要包装类?其实,随着我们对java面向对象的理解不断深入,我们会发现在万物皆对象的java语言中,其基本数据类型居然不是面向对象的,这不仅给类型之间的转化带来了很多麻烦,在基本数据类型的基础上也很难有更多的操作,为了解决这类问题在JDK1.5引入了两个功能:1.自动装箱  2.自动拆箱.

2.自动装箱与拆箱

  • 自动装箱:当我们把基本数据类型赋值给引用类型时,系统会将它自动包装成所需的实例对象,这样基本数据类型就达到了面向对象的效果.
  • 自动拆箱:当我们需要基本数据类型但此时传入的是包装类型,系统会自动拆箱,把包装类的值剥离出来.

1)隐式拆装箱:

public static void main4(String[] args) {
        Integer a = 123;//装箱
        int b = a;//拆箱[隐式的]
}

为什么叫隐式呢?我们来看反编译:

        通过反编译我们发现,在执行以上代码的过程中,编译器自动调用了Integer.valueof()方法装箱, intValue()方法拆箱.

2)显示拆装箱:

Integer a2 = Integer.valueOf(123);//显示装箱
int b2 = a2.intValue();//显示拆箱

         通过以上代码我们可以发现,装箱与拆箱的过程我们都可以看到,所以叫显示拆装箱.

三.面试常问:

1.以下代码结果为什么不同?

         通过前面知识我们可知给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()方法的返回值有一定的范围,那么这个范围是多大呢?我们可以查看lowhigh的原码.

 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对象,指向的地址不同那么值自然也就不同了.

         注意:除了DoubleFloat类型的valueof()方法外,其他基本类型的valueof()方法实现过程类似.这是因为浮点数的存储相较于其他类型会更加的复杂,我们可以简单观察一下源码. 感兴趣的读者下来可以深入了解一下,这里不过多讲述.

2.浅谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别:

         

        据了解Integer i = new Integer(xxx)这个方法已经过时,新一点的编译器可能无法通过编译.这恰好体现了new Integer(xxx)的不足之处:

1.new Integer(xxx)不会触发自动装箱机制,而第Integer i =xxx会.

2.执行效率上Integer i =xxx会更快.

3.综合考察:

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()的自动装箱类型只能和自己类型的比较.


总结

        以上就是深度剖析自动装箱与拆箱的全部内容了,如果我的总结对你有所启发和帮助,码字不易,麻烦给个三连哦!

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到