java自动装箱的陷阱

自动装箱和拆箱是java的一颗语法糖,在给我们带来使用便利的同时也带来一些疑惑,请看下面的代码:

 1 public class TestClass {
 2     public static void main(String args[]) {
 3         Integer a = 1;
 4         Integer b = 2;
 5         Integer c = 3;
 6         Integer d = 3;
 7         Integer e = 321;
 8         Integer f = 321;
 9         Long g = 3L;
10
11         System.out.println(c == d);
12         System.out.println(e == f);
13         System.out.println(c == (a+b));
14         System.out.println(c.equals(a+b));
15         System.out.println(g == (a+b));
16         System.out.println(g.equals(a+b));
17     }
18 }

大家看一下上面这段代码的输出结果应该是什么?



答案是:

T

F

T

T

T

F



这样的答案是不是出乎很多人的意料呢?我们一一来分析。

1. 首先我们明确一下"=="和equals方法的作用。

  "==":如果是基本数据类型,则直接对值进行比较,如果是引用数据类型,则是对他们的地址进行比较

  equals方法继承自Object类,在具体实现时可以覆盖父类中的实现。看一下Object中qeuals的源码发现,它的实现也是对对象的地址进行比较,此时它和"=="的作用相同。而JDK类中有一些类覆盖了oject类的equals()方法,比较规则为:如果两个对象的类型一致,并且内容一致,则返回true,这些类有:
java.io.file,java.util.Date,java.lang.string,包装类(Integer,Double等)。

2. java的常量池技术。java中的基本类型的包装类、其中Byte、Boolean、Short、Character、Integer、Long实现了常量池技术,(除了Boolean,都只对小于128的值才支持)。什么意思呢?对于范围在-128到127大小的数据,java会在常量池中提前生成这个范围的数据,只要是指向这些数据的包装类,都有相同的地址。而不在这个范围内的数据会到堆上new一个出来。

3. "=="在遇到算术运算符的情况下不会自动拆箱,以及他们的equals方法不处理数据类型转换的关系。

因此,对于 System.out.println(c == d); 他们指向常量池中同一个地址,返回True。

对于 System.out.println(e == f); 他们的值大于127,即使值相同,但是对应不同的内存地址,返回false。

对于 System.out.println(c == (a+b)); 他们指向常量池中同一个地址,返回True。

对于 System.out.println(c.equals(a+b)); 他们的值相同,而且类型相同,返回true。

对于 System.out.println(g == (a+b)); 他们指向常量池中同一个地址,返回True。

对于 System.out.println(g.equals(a+b)); 他们的值相同但是类型不同,返回false。

这下明白了吧?

时间: 2024-12-15 13:10:01

java自动装箱的陷阱的相关文章

java自动装箱与拆箱

基本数据(Primitive)类型的自动装箱(autoboxing).拆箱(unboxing)是J2SE 5.0提供的新功能,跟泛型.变长参数等一样,这也是一颗"语法糖",之前介绍jvm早期优化的时候说过,语法糖对运行期的代码没有任何影响,其目的仅仅是方便程序员使用,所有语法糖编译后都将会还原成基础语法.这次介绍的自动装箱和拆箱也不例外.看下头的例子: public class Demo { public static void main(String[] args) { Intege

java自动装箱拆箱总结

对于java1.5引入的自动装箱拆箱,之前只是知道一点点,最近在看一篇博客时发现自己对自动装箱拆箱这个特性了解的太少了,所以今天研究了下这个特性.以下是结合测试代码进行的总结. 测试代码: int a = 1; Integer b = 1; Integer c = 1; Integer d = 2; Integer e = 3; Integer f = 128; Integer g = 128; Long h = 3L; Double m = 4.0; Double n = 4.0; Float

Java 自动装箱和拆箱

JDK1.5之后的功能 自动装箱:指的是开发人员可以把一个基本数据类型直接赋给对应的包装类 自动拆箱:指开发人员可以把一个包装类对象直接赋给对应的基本数据类型 public static void main(String[] args) { Integer i = 1; //装箱 int j = i ; //拆箱 } public static void main(String[] args) { List list = new ArrayList(); list.add(1); int j=

Java自动装箱和自动拆箱操作

1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference Type(引用类型).基本类型的数值不是对象,不能调用对象的toString().hashCode().getClass().equals()等方法.所以Java提供了针对每种基本类型的包装类型.如下: Java基本数据类型 INDEX 基本类型  大小 数值范围 默认值 包装类型 1 boolea

java 自动装箱自动拆箱

1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference Type(引用类型).基本类型的数值不是对象,不能调用对象的toString().hashCode().getClass().equals()等方法.所以Java提供了针对每种基本类型的包装类型.如下: Java基本数据类型 INDEX 基本类型  大小 数值范围 默认值 包装类型 1 boolea

跟王老师学泛型(二):Java自动装箱与拆箱

Java 自动装箱与拆箱(Autoboxing and unboxing) 主讲教师:王少华 QQ群:483773664 学习目标: 掌握Java 基本数据对应的包装类 掌握Java 自动装箱与拆箱 一.基本数据类型对应的包装类 Java为每一种基本数据类型都提供了一个包装类,而这些包装类就在java.lang包中.Java共有8个包装类.如下图所示: 包装所有数字类型类都继承自Number类,Number类是一个抽象类. 二.什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).

【转】java 自动装箱与拆箱

java 自动装箱与拆箱 这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱): 其实按照我自己的理解自动装箱就可以简单的理解为将基本数据类型封装为对象类型,来符合java的面向对象:例如用int来举例: //声明一个Integer对象 Integer num = 10; //以上的声明就是用到了自动的装箱:解析为 Integer

java 自动装箱、拆箱

# java 自动装箱.拆箱 从 jdk 1.5 版本开始, 引入该功能. 一.自动装箱 将基本数据类型自动封装为对应封装类. 代码示例, Integer i = 100; 100属于基本类型int,会自动装箱,如下: Integer i = Integer.valueOf(100); 相当于, Integer i = new Integer(100); 二.自动拆箱 将封装类自动转换为对应的基本数据类型. 代码示例, Integer i = new Integer(100); int j =

Java自动装箱拆箱

一.装箱.拆箱定义 如果一个int型量被传递到需要一个Integer对象的地方,那么,编译器将在幕后插入一个对Integer构造方法的调用,这就叫做自动装箱.而如果一个Integer对象被放到需要int型量的地方,则编译器将幕后插入一个队intValue方法的调用,这就叫做自动拆箱. public static void main(String[] args) { // 装箱 Integer i1 = Integer.valueOf(1); // 自动装箱 Integer i2 = 1;// 默