说到== 与 equals 的区别,大多数小白可能就心想:
==不就是基本数据类型比较值,引用类型比较地址?
equals不就是比较引用类型值?
但凡看过Object源码就知道,原生equals和==没有区别!上源码:
// Object原生equals
public boolean equals(Object obj) {
return (this == obj);
}
这内部不就调用的 ==;况且一搜很多 == 与 equals的区别,置顶的帖子居然还是说 equals不就是比较引用类型值。。。
所以我们明确了第一点:原生的equals和==没有区别,都是比较引用类型地址。当然两个基础类型比较用不上equals。
我们知道JDK1.5之后java引入了自动装箱和自动拆箱机制。那如果是基础类型和对应的包装类进行比较呢?
我们来看下面几个代码
// 基础类型和对应的包装类进行比较
int i =200;
Integer j = 200;
System.out.println(j.equals(i));
System.out.println(i == j);
结果是
第一个是true,那我们就不得不看看Integer里面的equals源码了
// Integer里面的equals源码
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Integer中重写了equals方法,先是判断传入的Object对象是不是Integer类型或者Integer类型子类,然后强转Object对象为Integer类型,调用intValue()方法返回这个Object对象的值,和调用equals()的对象进行值比较。
拓展:那我们这个例子,equals()括号里面是基本数据类型,基本数据类型是Object的子类吗?
从下图我们可以看到,当1赋值给Object对象时,编译器没有报错,通过反射我们发现1自动装箱成了Integer
public static void main(String[] args) {
//编译器没报错
Object i = 1;
System.out.println(i.getClass().getName());
}
所以我们明白了Integer里面equals是优先比较包装类的,意思是说即使括号里是基础数据类型也会自动装箱再进行比较,先比较类型,再比较值。
我们再回过头看第二个true,也就是基础数据类型和对应包装类用==比较,也是返回true,如果 ==是和Integer里面equals一样优先比较包装类,那么把i装箱成integer,两个值超过127的integer用 == 比较肯定是false,地址不同了,如果两个Integer值是在-128 - 127,两个Integer会指向常量池的同一个地址,会返回true,但这不是我们现在讨论的情况。
由此我们明白了==是优先比较基础类型的,如果基础数据类型和对应包装类用 ==比较,会把包装类自动拆箱再比较。
小结:
1.原生的equals和==没有区别
2.在一个包装类和对应的一个基础类型进行比较时, ==是优先比较基础类型的,Integer里面equals是优先比较包装类的
3.==是两个都是基础类型时比较值,两个都是包装类型时比较地址,
equals两个都是包装类时,先比较类型,再比较值。