关于ArrayList中装箱与拆箱的问题

szhielelp 2015-02-02 10:45:04
package javatest;

import java.util.ArrayList;

public class Main {
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList<>();
al.add(1);
al.add(1);

System.out.println(al.get(0) == al.get(1));
System.out.println(new Integer(0) == new Integer(0));
}
}


为什么输出
true
false

我查看了一下get的源码


    public E get(int index) {
rangeCheck(index);

return elementData(index);
}


    E elementData(int index) {
return (E) elementData[index];
}


这个E不是Integer嘛,他并没有转换成int类型
为什么会这样,这两种情况有什么区别
...全文
657 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
wyc_ 2015-02-04
  • 打赏
  • 举报
回复
自动装箱的时候调用的Integer.valueOf函数,这个函数首先检查如果这个数在-128到127之间就直接返回缓存的值,否则就new一个新的出来。
oh_Maxy 2015-02-04
  • 打赏
  • 举报
回复
引用 12 楼 zfyq124 的回复:
[quote=引用 10 楼 u011106669 的回复:] 哥们,首先这个问题并不是ArrayList的装箱和拆箱的问题,它本质上是泛型的装箱和拆箱。泛型中定义的数据类型不能是基本数据类型,如果放了基本数据类型必须要进行装箱,其他的集合在使用泛型的时候也必须满足这个条件。你的这个问题和这段代码是等价的, Integer i1 = 1; Integer i2 = 1; System.out.println(i1==i2); Integer i3 = new Integer(1); Integer i4 = new Integer(1); System.out.println(i3==i4); 输出结果为true和false,i1和i2被进行装箱,在比较时又被拆箱,1等于1,结果为true。而i3和i4是两个对象,直接使用==将会比较他们的hashcode值,而它们都是new出来的,地址值肯定不一样,结果为false。
我觉得你的理解是错误的,应该是
引用 1 楼 oh_Maxy 的回复:
我来试着解释一下: 常量-127到+128,会自动装箱、拆箱。 每次装箱的时候,一个整数一直都对应一个封装类型对象,即:-127到+128会分别对应256个Integer对象。 当1需要装箱时,会找到1对应的Integer,第二次1再装箱时,还会找同一个对象。 效果应该等同如下: Integer i = new Integer(0); al.add(i); al.add(i); 所以当get的时候,返回的都是同一个地址的整型对象
这样的 Integer i1 = 128; Integer i2 = 128; System.out.println(i1 == i2);结果为false[/quote] 关于128的问题,请看2L的补充说明
xiaoai900525 2015-02-03
  • 打赏
  • 举报
回复
两个都是比较地址
多木多多木 2015-02-03
  • 打赏
  • 举报
回复
引用 12 楼 zfyq124 的回复:
[quote=引用 10 楼 u011106669 的回复:] 哥们,首先这个问题并不是ArrayList的装箱和拆箱的问题,它本质上是泛型的装箱和拆箱。泛型中定义的数据类型不能是基本数据类型,如果放了基本数据类型必须要进行装箱,其他的集合在使用泛型的时候也必须满足这个条件。你的这个问题和这段代码是等价的, Integer i1 = 1; Integer i2 = 1; System.out.println(i1==i2); Integer i3 = new Integer(1); Integer i4 = new Integer(1); System.out.println(i3==i4); 输出结果为true和false,i1和i2被进行装箱,在比较时又被拆箱,1等于1,结果为true。而i3和i4是两个对象,直接使用==将会比较他们的hashcode值,而它们都是new出来的,地址值肯定不一样,结果为false。
我觉得你的理解是错误的,应该是
引用 1 楼 oh_Maxy 的回复:
我来试着解释一下: 常量-127到+128,会自动装箱、拆箱。 每次装箱的时候,一个整数一直都对应一个封装类型对象,即:-127到+128会分别对应256个Integer对象。 当1需要装箱时,会找到1对应的Integer,第二次1再装箱时,还会找同一个对象。 效果应该等同如下: Integer i = new Integer(0); al.add(i); al.add(i); 所以当get的时候,返回的都是同一个地址的整型对象
这样的 Integer i1 = 128; Integer i2 = 128; System.out.println(i1 == i2);结果为false[/quote]哥们,你我说的。这涉及到了底层的设计。128这个数字,并不是在byte类型表示的范围内,byte类型表示的范围是-128到127,如果是在这个范围内,不会初始化新的空间。你可以尝试下127这个数字,它的输出结果。
zfyq124 2015-02-03
  • 打赏
  • 举报
回复
引用 10 楼 u011106669 的回复:
哥们,首先这个问题并不是ArrayList的装箱和拆箱的问题,它本质上是泛型的装箱和拆箱。泛型中定义的数据类型不能是基本数据类型,如果放了基本数据类型必须要进行装箱,其他的集合在使用泛型的时候也必须满足这个条件。你的这个问题和这段代码是等价的, Integer i1 = 1; Integer i2 = 1; System.out.println(i1==i2); Integer i3 = new Integer(1); Integer i4 = new Integer(1); System.out.println(i3==i4); 输出结果为true和false,i1和i2被进行装箱,在比较时又被拆箱,1等于1,结果为true。而i3和i4是两个对象,直接使用==将会比较他们的hashcode值,而它们都是new出来的,地址值肯定不一样,结果为false。
我觉得你的理解是错误的,应该是
引用 1 楼 oh_Maxy 的回复:
我来试着解释一下: 常量-127到+128,会自动装箱、拆箱。 每次装箱的时候,一个整数一直都对应一个封装类型对象,即:-127到+128会分别对应256个Integer对象。 当1需要装箱时,会找到1对应的Integer,第二次1再装箱时,还会找同一个对象。 效果应该等同如下: Integer i = new Integer(0); al.add(i); al.add(i); 所以当get的时候,返回的都是同一个地址的整型对象
这样的 Integer i1 = 128; Integer i2 = 128; System.out.println(i1 == i2);结果为false
多木多多木 2015-02-03
  • 打赏
  • 举报
回复
引用 10 楼 u011106669 的回复:
哥们,首先这个问题并不是ArrayList的装箱和拆箱的问题,它本质上是泛型的装箱和拆箱。泛型中定义的数据类型不能是基本数据类型,如果放了基本数据类型必须要进行装箱,其他的集合在使用泛型的时候也必须满足这个条件。你的这个问题和这段代码是等价的, Integer i1 = 1; Integer i2 = 1; System.out.println(i1==i2); Integer i3 = new Integer(1); Integer i4 = new Integer(1); System.out.println(i3==i4); 输出结果为true和false,i1和i2被进行装箱,在比较时又被拆箱,1等于1,结果为true。而i3和i4是两个对象,直接使用==将会比较他们的hashcode值,而它们都是new出来的,地址值肯定不一样,结果为false。
再稍微补充一下,jdk是从5.0版本之后支持自动装箱拆箱的。
多木多多木 2015-02-03
  • 打赏
  • 举报
回复
哥们,首先这个问题并不是ArrayList的装箱和拆箱的问题,它本质上是泛型的装箱和拆箱。泛型中定义的数据类型不能是基本数据类型,如果放了基本数据类型必须要进行装箱,其他的集合在使用泛型的时候也必须满足这个条件。你的这个问题和这段代码是等价的, Integer i1 = 1; Integer i2 = 1; System.out.println(i1==i2); Integer i3 = new Integer(1); Integer i4 = new Integer(1); System.out.println(i3==i4); 输出结果为true和false,i1和i2被进行装箱,在比较时又被拆箱,1等于1,结果为true。而i3和i4是两个对象,直接使用==将会比较他们的hashcode值,而它们都是new出来的,地址值肯定不一样,结果为false。
菜鸟程序元 2015-02-02
  • 打赏
  • 举报
回复
可以Integer 更换成别的类型试一试 System.out.println(al.get(0) == al.get(1)); //比较的是对象相对应的值 System.out.println(new Integer(0) == new Integer(0));//比较的是 对象的空间地址
szhielelp 2015-02-02
  • 打赏
  • 举报
回复
引用 2 楼 oh_Maxy 的回复:
纠正下:-128到+127
原来如此,那对于其他类型是否还有这种缓存机制? 一般情况下对于原生类型 是否equals()就绝对精确?
oh_Maxy 2015-02-02
  • 打赏
  • 举报
回复
纠正下:-128到+127
oh_Maxy 2015-02-02
  • 打赏
  • 举报
回复
我来试着解释一下: 常量-127到+128,会自动装箱、拆箱。 每次装箱的时候,一个整数一直都对应一个封装类型对象,即:-127到+128会分别对应256个Integer对象。 当1需要装箱时,会找到1对应的Integer,第二次1再装箱时,还会找同一个对象。 效果应该等同如下: Integer i = new Integer(0); al.add(i); al.add(i); 所以当get的时候,返回的都是同一个地址的整型对象
姜小白- 2015-02-02
  • 打赏
  • 举报
回复
System.out.println(al.get(0) == al.get(1)); 普通的Integer 比较的时候,java会将Integer对象拆箱为 int型的数值,所以这里相等。 System.out.println(new Integer(0) == new Integer(0)); 这里是new 出来的两个Integer 对象,任何时候new 出来的两个对象都是不相等的。 第二个条件如果将== 换为 equals 的话,那是相等的,这时,java又将Integer对象拆箱为int值了。
JPF1024 2015-02-02
  • 打赏
  • 举报
回复
这个跟创建了几个对象是一样一样的..

  System.out.println(al.get(0) == al.get(1));//两个都指向一个地址
        System.out.println(new Integer(0) == new Integer(0));//由于new会新建对象,因此指向两个不同的地址
就是这样,跟装箱拆箱没关系
yongbuyanqi88888 2015-02-02
  • 打赏
  • 举报
回复
System.out.println(al.get(0) == al.get(1)); -- 值比较 System.out.println(new Integer(0) == new Integer(0)); --地址比较 了解哈:使用等号做比较时的特点
oh_Maxy 2015-02-02
  • 打赏
  • 举报
回复
引用 3 楼 szhielelp 的回复:
[quote=引用 2 楼 oh_Maxy 的回复:] 纠正下:-128到+127
原来如此,那对于其他类型是否还有这种缓存机制? 一般情况下对于原生类型 是否equals()就绝对精确?[/quote] 基本类型都会有的。 基本类型的封装类型逻辑相比,一般使用equals比较好。可以理解精确

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧