a.equals(b)背后的秘密

491 阅读3分钟

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

写在前面

平常开发中,大家都用什么方法来判断两个值是否相等,脱口而出的是equals,先给大家个结论,那就是不建议大家a.equals(b)去判断是否相等,看完本篇文章就知道了,大家都知道的是判断对象是否为空 是否相同都是拿== 来判断,那么不是对象呢。

当值是null的情况

1、a.equals(b) , a 是null

null.equals("abc")    →   抛出 NullPointerException 异常

这种意料之内,null是不能干任何事的,否则都会报空指针的

2、a.equals(b), a不是null, b是null

"abc".equals(null)    →   返回 false

可以看到 这次不报错了。而且结果确实为false。

3、a和b都为null时,我们看下(肯定也报空指针)

null.equals(null)     →   抛出 NullPointerException 异常

也经常拿Objects来判断 。Objects.equals(a, b)比较时, 若a 和 b 都是null, 则返回 true, 如果a 和 b 其中一个是null, 另一个不是null, 则返回false。注意:不会抛出空指针异常。

Objects.equals(null, "abc")    →   返回 false

Objects.equals("abc",null)     →   返回 false

Objects.equals(null, null)     →   返回 true

接下来再看当是空字符串的情况

值是空字符串

1、a 和 b 如果都是空值字符串:""

"".equals("")       →   返回 true

1、如果a和b其中有一个不是空值字符串,则都会返回false;

"abc".equals("")    →   返回 false

"".equals("abc")    →   返回 false

再看Objects

Objects.equals("abc", "")    →   返回 false

Objects.equals("","abc")     →   返回 false

Objects.equals("","")        →   返回 true

所以说当值是空字符串的时候 这样判断是没有问题的。

我们看下源码,为什么会出现这种差异

究其源码

先来看Objec根类 equals

public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }
    
    //首先this不可能去拿null去判断 所以null去equals行不通
    //obj传进来的可以为空,因为是拿 == 去判断的 
    //归根到底还是==去判断
    public boolean equals(Object obj) {
        return (this == obj);
    }
    
    ...
}

接下来再看Objecs中的equals

public final class Objects {
    private Objects() {
        throw new AssertionError("No java.util.Objects instances for you!");
    }
 
    /**
     * 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));
    }
    ...
}
  • 首先,进行了对象地址的判断,如果是真,则不再继续判断。

  • 如果不相等,后面的表达式的意思是,先判断a不为空,然后根据上面的知识点,就不会再出现空指针。

  • 所以,如果都是null,在第一个判断上就为true了。如果不为空,地址不同,就重要的是判断a.equals(b)。

总结

当Object.equals 第一值要判空,或者直接用Objects.equals去判断

OK。今天我们就学习到这里,分享一点小细节,积少成多。我们下期再见 加油!

弦外之音

copy对象,这个操作有点骚!

干货!SpringBoot利用监听事件,实现异步操作