java 装箱_java中的装箱与拆箱

一、基本数据类型 对象类型

1、首先想一个问题,有了基本类型之后为什么还要有包装器类型呢?

核心:让基本类型具备对象的特征,实现更多的功能.

Java是一个面相对象的编程语言,基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型。

我们在使用集合类型map、list时就一定要使用包装类型而非基本类型,它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。

int i = 1;

Map map= newHashMap();

map.put(i,12); //系统会自动将i装箱为Integer类型的对象,然后再存入集合中

2、在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行:

Integer i =new Integer(10);

而在从Java SE5开始就提供了自动装箱的特性,如果要生成一个数值为10的Integer对象,只需要这样就可以了:

Integer i =10;

这个过程中会自动根据数值创建对应的 Integer对象,这就是装箱。

那什么是拆箱呢?顾名思义,跟装箱对应,就是自动将包装器类型转换为基本数据类型:

e89dfcfd0db2115d0811e621feeb79a3.png

从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法。

其他的也类似,比如Double、Character。

三、相关问题

1.下面这段代码的输出结果是什么?

public classMain {public static voidmain(String[] args) {

Integer i1= 100;

Integer i2= 100;

Integer i3= 200;

Integer i4= 200;

System.out.println(i1==i2);

System.out.println(i3==i4);

}

}

也许有些朋友会说都会输出false,或者也有朋友会说都会输出true。但是事实上输出结果是:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

true

false

View Code

为什么会出现这样的结果?输出结果表明i1和i2指向的是同一个对象,而i3和i4指向的是不同的对象。此时只需一看源码便知究竟,下面这段代码是Integer的valueOf方法的具体实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static Integer valueOf(inti) {if(i >= -128 && i <=IntegerCache.high)return IntegerCache.cache[i + 128];else

return newInteger(i);

}

View Code

而其中IntegerCache类的实现为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

private static classIntegerCache {static final inthigh;static finalInteger cache[];static{final int low = -128;//high value may be configured by property

int h = 127;if (integerCacheHighPropValue != null) {//Use Long.decode here to avoid invoking methods that//require Integer's autoboxing cache to be initialized

int i =Long.decode(integerCacheHighPropValue).intValue();

i= Math.max(i, 127);//Maximum array size is Integer.MAX_VALUE

h = 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++);

}privateIntegerCache() {}

}

View Code

从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。

上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。

2.下面这段代码的输出结果是什么?

public classMain {public static voidmain(String[] args) {

Double i1= 100.0;

Double i2= 100.0;

Double i3= 200.0;

Double i4= 200.0;

System.out.println(i1==i2);

System.out.println(i3==i4);

}

}

也许有的朋友会认为跟上面一道题目的输出结果相同,但是事实上却不是。实际输出结果为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

false

false

View Code

在这里只解释一下为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。

注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。

Double、Float的valueOf方法的实现是类似的。

3.下面这段代码输出结果是什么:

public classMain {public static voidmain(String[] args) {

Boolean i1= false;

Boolean i2= false;

Boolean i3= true;

Boolean i4= true;

System.out.println(i1==i2);

System.out.println(i3==i4);

}

}

输出结果是:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

true

true

View Code

至于为什么是这个结果,同样地,看了Boolean类的源码也会一目了然。下面是Boolean的valueOf方法的具体实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static Boolean valueOf(booleanb) {return (b ?TRUE : FALSE);

}public static final Boolean TRUE = new Boolean(true);public static final Boolean FALSE = new Boolean(false);

View Code

4.谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。

当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:

1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;

2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。

5.下面程序的输出结果是什么?

public classMain {public static voidmain(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(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));

System.out.println(g.equals(a+h));

}

}

先别看输出结果,读者自己想一下这段代码的输出结果是什么。这里面需要注意的是:当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。明白了这2点之后,上面的输出结果便一目了然:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

true

false

true

true

true

false

true

View Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值