前言: Objects.equals()方法是java.util下的一个工具类,使用它可以进行两个对象equals的比较,避免繁琐的null指针判断。
这里写目录标题
本文由代码示例展开,以源码断点调试进行分析,Objects.equals()方法使用时容易忽略的一些问题。
1. Objects.equals()官方源码
这里我们先看Objects.equals()的官方源码
/**
* Returns {@code true} if the arguments are equal to each other
* and {@code false} otherwise.
* Consequently, if both arguments are {@code null}, {@code true}
* is returned and if exactly one argument is {@code null}, {@code
* false} is returned. Otherwise, equality is determined by using
* the {@link Object#equals equals} method of the first
* argument.
*
* @param a an object
* @param b an object to be compared with {@code a} for equality
* @return {@code true} if the arguments are equal to each other
* and {@code false} otherwise
* @see Object#equals(Object)
*/
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
2. 分析如下代码的执行结果
public static void main(String[] args) {
Integer integer1 = Integer.valueOf(1);
Integer integer200 = Integer.valueOf(200);
Integer integer100 = Integer.valueOf(100);
Long long200 = 200L;
Byte Byte100 = (byte) 100;
byte byte100 = (byte) 100;
System.out.println("--------------------Integer-----------------------");
System.out.println(Objects.equals(integer1, 1)); // true
System.out.println(Objects.equals(integer200, 200)); // true
System.out.println(Objects.equals(integer100, byte100)); // false
System.out.println(Objects.equals(integer100, Byte100)); // false
System.out.println("--------------------Long--------------------------");
System.out.println(Objects.equals(long200, 200L)); // true
System.out.println(Objects.equals(long200, 200)); // false
System.out.println(Objects.equals(long200, integer200)); //false
System.out.println("--------------------Byte--------------------------");
System.out.println(Objects.equals(Byte100, 100)); // false
System.out.println(Objects.equals(Byte100, (byte) 100)); // true
System.out.println(Objects.equals(Byte100, byte100)); // true
System.out.println("--------------------byte--------------------------");
System.out.println(Objects.equals(byte100, 100)); // false
System.out.println(Objects.equals(byte100, (byte) 100)); // true
System.out.println(Objects.equals(100,byte100)); // false
}
3. 重点疑问解答
3.1 System.out.println(Objects.equals(integer100, byte100));
这两个都是赋值100
,但是使用Objects.equals()进行比较的时候却发现,返回的是false,这是为什么呢?下面在源码中打断掉调试,如图:
第一步、打上断点
第二步、断点跳入Objects.equals()方法
可以看到我们的byte100基本数据类型变量,已经被自动装箱为Byte包装类
了,下一步就是走的Integer的equals方法了
第三步、断点跳入Integer.equals()
方法,由此可见,因为Byte并非是Integer的实例,所以Integer.equals()方法直接返回false,而不是进行值的比较。
3.2 System.out.println(Objects.equals(long200, 200));
一个是200L一个是200,对于我们惯性思维肯定认为是true,但是使用Objects.equals()进行比较的时候却发现,返回的是false
,这是为什么呢?下面在源码中打断掉调试,如图:
第一步、打上断点
第二步、由此可以发现,200的基本数据类型(int)被自动装箱为Integer
了
第三步、下一步,断点直接跳入到了Long.equals()方法中,如图:
因为两者根本不是同一个对象类型,所以直接返回false,原理同上3.1
总结:上述问题的本质原因,是因为使用Object.equals()方法时,会将基本数据类型进行自动装箱后,进行对应的包装类的equals比较。而我们忽略了
类型的比较
,仅仅关注到了值的比较。
说了这么多,其实这也不算是Objects.equals()方法的坑,只是我们想当然的认为和理解与计算机代码执行的不一致罢了,这也告诉我们如下道理。我们使用别人造好的轮子的时候,在快捷高效方便的书写代码的时候,一定要清楚它们对应的功能边界,使用场景,失效场景,这样才能帮助我们更好的写出少bug的正确代码。