为什么Java中==比较两个值相等的对象返回false,而用==比较两个值相等,基本数据类型不相同的数据返回true?
先看是不是,再问为什么。
首先看值相同的两个对象的==比较:
public class Obj{
private int num;
public Obj(int num){
this.num = num;
}
}
public class Test{
public static void main(String[] args){
Obj obj1 = new Obj(1);
Obj obj2 = new Obj(1);
System.out.println(obj1 == obj2);
}
}
这个输出结果应该会一点java的人都知道返回的是false,因为==比较的是是否完全是同一个对象,也就是是否在同一片内存空间上。
下面看一下值相等的两个基本数据类型的==比较:
public class Test{
public static void main(String[] args){
int i1 = 1;
byte i2 = 1;
System.out.println(i1 == i2);
}
}
这个输出结果想必大多数人也能答出来,结果是true。
好,现在来看看为什么。不要把这些东西想得太想当然,应该尽可能多问一个为什么。
首先要知道这些局部变量和引用存放在什么地方,实际上是存放在局部变量表里,这是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。局部变量的容量以变量槽(slot)为最小单位,JVM规范没有明确指出一个slot应该占有多少内存空间,只是说一个slot应该能存放一个boolean、byte、char、short、int、float、reference或者returnAddress类型的数据。
说到这里应该明白了,比如上面的i1,i2都是以值的形式存在于虚拟机栈中的局部变量表里的slot,而且是不同的slot,然而obj1和obj2存的分别是指向不同堆内对象的reference。
那么值相等的基本数据类型之间用==比较为true以及值相等的对象之间的==比较为false的原因也水落石出了。
==可以看成是比较局部变量表中的slot中存着的东西,对于值相等的对象的比较,比较的也就是reference,reference指向的Java堆中对象都不同,当然也就不一样。
当使用==比较值相等的基本数据类型的时候,比较的还是slot中存着的东西,这个时候slot中存着的是基本数据类型的值,所以比较的是基本数据类型的值,所以是相等的。
这是我的个人看法,知乎上有种很多人拥护的看法是对于一个基本数据类型会把它封装成对象放在堆内,如果有新的数据类型值和他一样就直接使用这个堆内对象,所以值相等的时候==返回为true,在我看来这样的解答是很不合理的。
以上均是个人看法,如果有错误请指出