public class Test {
public static void main(String[] args) {
Integer n1 = 127;
Integer n2 = 127;
System.out.println(n1 == n2);//输出结果为true
Integer n3 = 128;
Integer n4 = 128;
System.out.println(n3 == n4);//输出结果为false
}
}
以上代码中,明明四个Integer对象的生成方式和比较方式都是相同的,为什么比较结果却不同呢?这里涉及到包装类以及==这个操作符的含义,先解释一下这些内容再去讨论上面代码中的问题。
Java 语言是典型的面向对象编程语言,但八种基本数据类型并不支持面向对象编程,有时就会带来不便。所以,Java为每种基本数据类型分别设计了对应的包装类。
装箱和拆箱是为了实现包装类和基本数据类型之间的转换。
public static void main(String[] args) {
Integer a = new Integer(10); //手动装箱
int aa = a.intValue(); //手动拆箱
Integer b = 10; //自动装箱
int bb = b; //自动拆箱
}
Java 1.5 之后支持自动拆箱装箱,虽然看上去简单了,但其实只是把原本要new一个空间的工作交给了编译器。比如下面这一行代码:
Integer a = 10;
实际上相当于编译器自动作以下的语法编译:
Integer i = new Integer(100);
使用“==”时,对基本数据类型(如int,double等),比较的是变量存储的数值的大小,若相等则返回true。
而对引用数据类型(如Integer,Double等)比较的是变量指向的对象在内存中存储的地址,若两个对象在内存中地址不同,则即使内容相同也仍然返回true。
equals 方法在Object类中比较的仍然是是两个变量指向的对象在内存中存储的地址是否相等。所以一些继承Object的类重写了 equals 方法,比如Integer,String等,这些类使用 equals 方法时,会比较两个对象的内容是否相同,而非比较内存地址是否相同。
开头的代码之所以会出现那种结果,是因为Integer使用了缓冲池技术,也就是说,在给一个新的Integer对象赋值时,先看常量池中是否存在其他Integer对象的引用,其值和这个新的Integer对象所要赋的值相同,若有就直接返回这个引用,若没有,就创建这个Integer对象并在常量池中记录下这个引用。但问题在于,只有值在 [-128,127]中时才会去访问常量池查找引用,否则就直接new一个新的对象,所以才会出现==操作出现false的情况, Byte、Short、Long、Character 这5种整型包装类也是如此。
注意,若是基本数据类型和包装类使用“==”进行比较,则包装类会自动拆箱,比较数值的大小,如下:
public static void main(String[] args) {
int a = 200;
Integer b = 200;
System.out.println(a == b);//输出true
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_46027243/article/details/120516099
内容来源于网络,如有侵权,请联系作者删除!