Java空指针检查为什么使用==而不是.equals()?

149
在Java中,我听说进行空值检查时应该使用==而不是.equals()。这是为什么呢?

15
最简单的方法是使用equals()进行空值检查,试一试就会立即明显。 - Goran Jovic
顺便提一下,使用关键词“java null check”(不带引号)进行谷歌搜索,其中之一的热门搜索结果是此线程,它包含了与这里答案相同的信息。 - Mitch Schwartz
16个回答

208
他们是两个完全不同的概念。 == 比较变量所包含的对象引用(如果有的话)。.equals() 检查两个对象是否根据它们的相等约定相等。两个不同的对象实例根据它们的约定可能会“相等”。另外,由于 equals 是一个方法,如果你试图在 null 引用上调用它,你将得到一个 NullPointerException,这是一个小细节。
例如:
class Foo {
    private int data;

    Foo(int d) {
        this.data = d;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != this.getClass()) {
           return false;
        }
        return ((Foo)other).data == this.data;
    }

    /* In a real class, you'd override `hashCode` here as well */
}

Foo f1 = new Foo(5);
Foo f2 = new Foo(5);
System.out.println(f1 == f2);
// outputs false, they're distinct object instances

System.out.println(f1.equals(f2));
// outputs true, they're "equal" according to their definition

Foo f3 = null;
System.out.println(f3 == null);
// outputs true, `f3` doesn't have any object reference assigned to it

System.out.println(f3.equals(null));
// Throws a NullPointerException, you can't dereference `f3`, it doesn't refer to anything

System.out.println(f1.equals(f3));
// Outputs false, since `f1` is a valid instance but `f3` is null,
// so one of the first checks inside the `Foo#equals` method will
// disallow the equality because it sees that `other` == null

你是指 public int data 吗? - Jé Queue
@Xepoch:不,我一般不会创建公共字段(尽管对于这个例子来说无论如何都没有太大关系)。为什么呢? - T.J. Crowder
@T.J. Crowder:“它们是完全不同的东西..”一般来说是的。但是,如果我理解正确的话,两者的默认实现是相同的。从源代码来看,.equals() 基本上是进行 == 检查。http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/java/lang/Object.java - Ayush
2
@Ayush - 是的,在Object中这是默认值。但是在许多JDK类中被覆盖。但是关键不在于实现,而在于语义。 (旁注:JDK7已经非常过时了。) - T.J. Crowder
3
@RogerWang - 好问题!答案是,null 不是一个对象,它是一个对象 引用(一个空的引用)。它是我们可以在代码中直接写出来的唯一对象引用。因此 Object a = null; Object b = null; 表示 a == b 为真,因为两个变量包含相同的对象引用(单一的全局空引用)。 - T.J. Crowder
显示剩余2条评论

48

除了被接受的答案(https://dev59.com/FW855IYBdhLWcg3wKw9Y#4501084)之外:

从Java 1.7开始,如果你想比较两个可能为空的对象,我推荐使用这个函数:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

这个类包含用于操作对象的静态实用程序方法。这些实用程序方法包括在计算对象的哈希码、返回对象的字符串和比较两个对象时,能够处理空值或允许空值的方法。

自: 1.7


4
为了让其他人更容易看到(请参考chin90的答案或JavaDoc),Objects.equals(null, null)将返回true - 请记住。 - Thomas
Intellij总是建议在我的代码中使用Object.equals()而不是== - kaushalpranav

45

如果你在null上调用.equals()方法,你会得到一个NullPointerException

因此,在调用任何适用的方法之前,始终建议检查它们是否为null

if(str!=null && str.equals("hi")){
 //str contains hi
}  

还可以参见


49
你的示例通常更好地编写为if("hi".equals(str)) - ColinD
4
如果对象引用为null,则调用someObject.equals(null)会引发NullPointerException异常,而不会进入equals方法。关键不在于equals方法是否包含空检查。 - Dave Costa
3
@ColinD 我同意,只是在这里演示。 - jmj
2
始终建议不惜一切代价避免使用null,这样您就根本不需要进行null检查 ;)。 - cthulhu
4
你可以随时使用Objects.equals(a, b)。它不会引发空指针异常,但仍取决于“a”和“b”的“equal”方法。 - Dominik Minc

30

在Java中,0或null是简单类型而不是对象。

equals()方法不适用于简单类型。简单类型可以用==进行匹配。


6
请为实际有用的答案点赞,不要选择那些显而易见的“将返回NullPointerException”的回答。 - volk
对于“简单类型”,希望大家理解null不是原始类型,而是对象的默认值,并且有一些有趣的事实:https://www.geeksforgeeks.org/interesting-facts-about-null-in-java/amp/ - Treefish Zhang
顺便说一下,您不能将原始类型赋予 null 值,因此是的,楼主想要检查对象的 null 安全性而不是原始类型。 - Guilherme Taffarel Bergamin

6

Object.equals是空指针安全的,但请注意,如果两个对象都为null,object.equals将返回true,因此请确保在使用object.equals进行比较之前检查您要比较的对象不为空(或者不包含null值)。

String firstname = null;
String lastname = null;

if(Objects.equals(firstname, lastname)){
    System.out.println("equal!");
} else {
    System.out.println("not equal!");
}

以上示例代码将返回相等!


根据JavaDoc中所述(阅读这些文档总是明智的):因此,如果两个参数都为null,则返回true。 :) - Thomas
我的意思是... 如果两个都是null,它们确实相等... 我认为这对使用 Objects.equals()的人来说应该是显而易见的。 - Guilherme Taffarel Bergamin

5
foo.equals(null)

如果foo为空会发生什么?

你会得到一个NullPointerException(空指针异常)。


4

如果一个对象变量为null,则无法调用equals()方法,因此应该对null进行对象引用检查。


2
根据来源,默认方法实现使用什么并不重要。
public boolean equals(Object object) {
    return this == object;
}

但是在自定义类中,你无法确定 equals 方法。


这很重要,因为equals只能返回false或者引起NullPointerException(如果覆盖的equals方法是无意义的,则可能会返回其他内容)。 - Tom

2

如果我们使用 .equals 方法

if(obj.equals(null))  

// Which mean null.equals(null) when obj will be null.

当您的 obj 为空时,将抛出 Null Point Exception 异常。因此,我们应该使用 ==。
if(obj == null)

它将比较这些引用。


2

如果你尝试在一个null对象引用上调用equals方法,那么你会得到一个空指针异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接