java 手动装箱与拆箱_java装箱与拆箱的深入理解

Java有一个类型系统有两个部分组成,包含基本类型(byte、char、int、short、long、float、double、boolean)和引用类型。而基本类型则对应着各自的引用类型,称为装箱的基本类型。而引用类型对应着各自的基本类型,称为拆箱的基本类型。对应的类型为:(Byte、Character、Integer、Short、Long、Float、Double、Boolean)

下面一具体例子来说明装箱与拆箱

//java 1.5之前创建一个Integer对象

Integer i = new Integer(10);

//java 1.5之后有了装箱的特性,直接用下列方式生成一个Integer对象

//在这个过程中会将int 类型的10自动装箱成为Integer类型

Integer i = 10;

//拆箱 输出的值为20,这个过程中,会先将Integer类型的j自动拆箱为基本类型的10,最后完成运算

Integer j = new Integer(10);

int k = 10;

System.out.print(j+k);

下面来说说基本数据类型与其对应的引用类型的区别:

基本类型只有值,而装箱基本类型既具有值也具有它们对象的同一性(就是两个装箱的基本类型具有相同的值和不同的同一性(对象不一样))

基本类型只有功能完备的值,而每个装箱类型不仅具有完备的值还具有所有功能值之外的null。

基本类型通常比装箱基本类型更节省时间和空间。

下面来举一个《Effective java中》的一个例子进行分析

Comparator comparator = new Comparator()

{

public int compareTo(Integer first,Integer second)

{

return first > second ? 1:first == second ? 0 : -1;

}

}

//这两个Integer实例都表示相同的值42

Integer a = new Integer(42);

Integer b = new Integer(42);

int c = comparator.compareTo(a,b);

//返回值多少 0 ? 但实际结果却是-1,难道 42 < 42 ?

下面就来解释上面例子的原因:

首先执行 a>b,两个Integer都自动拆箱为42,不成立,则执行 a==b,乍一看,没什么问题,42==42没问题啊,但实际上这是违反了了装箱的同一性,因为a和b都是引用类型,根据上述两个装箱类型具有相同的值和不同的同一性,只是两个对象的比较,即这两个对象是不同对象,所对应的内存也不一样,a!=b。所有正确答案应该是 -1。

现在来说说装箱和拆箱是怎么实现的:

public static void main(String[] args){

Integer i = 10;

int j = 10;

System.out.print("i+j = "+(i+j));

}

打印结果为:

0274c8a9d91e

Paste_Image.png

反编译class文件得到:

0274c8a9d91e

Paste_Image.png

第一行是装箱过程,查看源码实际是调用了Integer.valueOf(int)方法返回一个Integer实例

第三行进行加法运算的时候是拆箱过程,将Integer实例i拆箱为int型,然后进行加法运算,实际是调用了Integer.intValue()方法返回一个int型数据。

关于装箱与拆箱大致的都讲的差不多了。下面举几个面试中关于装箱与拆箱会问到的例子:

public class Main

{

public static void main(String[] args)

{

Integer i1 = 100;

Integer i2 = 100;

Integer i3 = 200;

Integer i4 = 200;

System.out.println(i1==i2); //返回true

System.out.println(i3==i4); //返回false

}

}

下面来解释下这个原因

//这是装箱的源码

public static Integer valueOf(int i) {

return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];}

/** * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing */

private static final Integer[] SMALL_VALUES = new Integer[256];

static {

for (int i = -128; i < 128; i++){

SMALL_VALUES[i + 128] = new Integer(i);

}

}

//当值在[-128,127)之间时,装箱操直接取已经cache好的Integer实例,所以i1==i2,当大于127时,每次都是new出来的Integer,指向不同的对象,所以i3!=i4

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(c==d); //true

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));//false

System.out.println(g.equals(a+b));//false

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

}

}

// Example 1: == comparison pure primitive – no autoboxing

int i1 = 1;

int i2 = 1;

System.out.println("i1==i2 : " + (i1 == i2)); // true

// Example 2: equality operator mixing object and primitive

Integer num1 = 1; // autoboxing

int num2 = 1;

System.out.println("num1 == num2 : " + (num1 == num2)); // true

// Example 3: special case - arises due to autoboxing in Java

Integer obj1 = 1; // autoboxing will call Integer.valueOf()

Integer obj2 = 1; // same call to Integer.valueOf() will return same

// cached Object

System.out.println("obj1 == obj2 : " + (obj1 == obj2)); // true

int obj3 = 3;

Integer obj4 = 3;

Integer obj5 = new Integer(3);

System.out.println("obj4 == obj5 : " + (obj4 == obj5));//false

System.out.println("obj3 == obj5 : " + (obj3 == obj5));//true

// Example 4: equality operator - pure object comparison

Integer one = new Integer(1); // no autoboxing

Integer anotherOne = new Integer(1);

System.out.println("one == anotherOne : " + (one == anotherOne)); // false

//当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值