前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 为什么需要包装类,如何使用包装类?

Java 为什么需要包装类,如何使用包装类?

作者头像
水货程序员
修改2018-12-03 16:37:45
6.6K0
修改2018-12-03 16:37:45
举报
文章被收录于专栏:javathings

Java 是号称面向对象的语言,所有的类型都是引用类型。 Object 类是所有类的父类,而且是唯一不用指定明确继承的类。但是基本类型如 int 不是引用类型,也不是继承自 Object,所以 Java 需要一个这样的包装类来使其面向对象的完整性。 包装类同时也可以实现可空类型,即一个数值是空的。Java 集合中也只能放入包装类型,而不支持基本类型。

包装类与自动装箱拆箱

装箱就是 Java 将基本类型转换成对应的包装类型,比如将 int 转换成 Integer 对象。反之将 Integer 转换成 int 值,则称为拆箱。 装箱时,调用 valueOf 方法实现,比如 Integer.valueOf(100); 拆箱时,调用对应的 xxxValue 方法,比如 intValue() 方法。 自动装箱拆箱功能是 java1.5 后才有的。自动装箱拆箱时,由 Java 编译器自动实现转换。 赋值操作的时候,当两边类型不同,就会发生自动装箱拆箱。 自动装箱: 比如:Integer i = 100; 相当于编译器自动作以下的语法编译:

代码语言:javascript
复制
Integer i = Integer.valueOf(100);
ArrayList intList = new ArrayList();
intList.add(1); //自动装箱

自动拆箱:

代码语言:javascript
复制
Integer i = 10; //装箱
int t = i; //拆箱,实际上执行了 int t = i.intValue();
System.out.println(i++);//拆箱

包装类相加时,也会自动拆箱。

代码语言:javascript
复制
Integer a=new Integer(1);
Integer b=new Integer(2);
System.out.println(a+b);//自动拆箱
自动装箱有性能损耗,在循环中应避免
代码语言:javascript
复制
Integer sum = 0;
for(int i=0; i<100; i++){
sum+=i;
}

上面的代码 sum+=i 可以看成 sum = sum + i,但是这个操作会把 sum 先拆箱,然后相加后再装箱。等价于下面的代码: Integer sum = new Integer(sum.intValue() + i;);

包装类的比较

==符号是进行引用的比较。这个比较不会引起自动拆箱。

代码语言:javascript
复制
Integer a=128;
Integer b=128;
System.out.println("a==b : " + (a == b)); //false,不会自动拆箱,比较的是引用,不是同一个地址引用
System.out.println("a>b : " + (a > b)); // false,会自动拆箱
System.out.println("a<b : " + (a < b)); // false,会自动拆箱

但是,由于 JVM 会缓存-128 到 127 的 Integer 对象,所以当包装类的值在-128 到 127 的范围内,判等比较的是同一个引用。

代码语言:javascript
复制
Integer a=127;
Integer b=127;
System.out.println("a==b : " + (a == b)); //true,是同一个地址引用

那么对于 128 这样数字的包装类,判等该怎么做?很简单,手动拆箱,或者用 equals 方法。

代码语言:javascript
复制
Integer a=128;
Integer b=128;
System.out.println("a.intValue()==b.intValue() : " + (a.intValue()==b.intValue())); //手动拆箱,true
System.out.println("a.equals(b) : " + (a.equals(b))); //true
 

equals 方法会拆箱后,根据基本类型比较,所以比较的是两者值的大小。

包装类型和基本类型用==比较的时,会发生拆箱
代码语言:javascript
复制
Integer b=128;
int c=128;
long d=128;
System.out.println("b==c : " + (b == c)); //true ,b自动拆箱
System.out.println("b==d : " + (b == d));//true b自动拆箱,并且会自动提升类型
 

当包装类和基本类型用 equals 比较时,会出现问题了。

代码语言:javascript
复制
System.out.println("b.equals(c) : " + (b.equals(c))); //true
System.out.println("b.equals(d) : " + (b.equals(d))); //false

发生了什么?看一下 equals 方法源码就知道了

代码语言:javascript
复制
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

基本类型会被自动装箱,放入 equals 方法,然后第一步会判等是否是 Integer 的类型,那么 long d 会被装箱成 Long,所以类型就不一致,直接不进行比较,返回 false。而 int c 会装箱成 Integer 而类型一致,可以继续比较下去。

总结

包装类是一个对象,基本类型不是。 包装类和基本类型可以互相转换,转换的过程称之为装箱拆箱,可以手动转换,也可自动转换。 包装类比较大小的时候有很多坑,比如: ==比较引用,Integer 类型只有在-128 到 127 的范围内,才会持有同一个引用。 equals 方法会先比较类型是否一致,不一致直接 false。 最佳的操作实践是,比较大小的时候,统一先手动拆箱,然后再比较值。

参考:

http://coderevisited.com/boxing-and-unboxing-in-java/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 包装类与自动装箱拆箱
  • 自动装箱有性能损耗,在循环中应避免
  • 包装类的比较
  • 包装类型和基本类型用==比较的时,会发生拆箱
  • 总结
  • 参考:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档