Java null检查为什么使用==代替.equals()


125

在Java中,我被告知在执行null检查时应使用==而不是.equals()。是什么原因呢?


12
最简单的方法是尝试使用null检查equals()并查看。当您尝试尝试时,它将立即变得很明显
Goran Jovic 2010年

顺便说一句,使用关键字“ java null check”(不带引号)的google搜索使我成为该线程的热门歌曲之一,该线程的信息与此处的答案相同。
米奇·施瓦兹

Answers:


179

他们是两个完全不同的东西。==比较变量包含的对象引用(如果有)。根据相等性的含义.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
JE队列

@Xepoch:不,我一般不创建公共字段(尽管无论哪种方式对于此示例来说都没有关系)。为什么?
TJ Crowder

@TJ Crowder“它们是两件事完全不同。”通常是的。但是,如果我的理解正确的话,两者的默认实现是相同的。查看源代码,.equals()基本上执行==检查。hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/...
AYUSH

1
@Ayush-这是默认设置Object,是的。但是,它被大量的JDK类覆盖。但是,重点不是实现,而是语义。(旁注:JDK7已经过时。)
TJ Crowder

是的,这很有意义,只是想澄清一下。
Ayush

38

如果您调用.equals()null您将获得NullPointerException

因此,始终建议在适用的地方调用方法之前检查无效性

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

另请参阅


34
通常,您的示例最好写成if ("hi".equals(str))
ColinD 2010年

3
@ user368186:问题不在于equals方法是否包含空检查。如果对象引用为null,则该调用someObject.equals(null)将引发a,NullPointerException而无需输入equals方法。
戴夫·科斯塔

2
@ColinD同意只在这里演示
Jigar Joshi 2010年

2
始终不遗余力地建议避免空值,因此您根本不需要空值检查;)。
fwielstra 2010年

2
您可以始终使用 Objects.equals(a, b)它不会引发NullPointerException,但是它仍然取决于“ a”和“ b”的“相等”方法
Dominik Minc

29

除了接受的答案(https://stackoverflow.com/a/4501084/6276704):

从Java 1.7开始,如果要比较两个可能为null的对象,我建议使用此函数:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

此类包含用于对对象进行操作的静态实用程序方法。这些实用程序包括用于计算对象的哈希码,返回对象的字符串以及比较两个对象的null安全或null容忍方法。

从:1.7


2
只是为了使其对其他人更可见(请参阅chin90的答案或JavaDoc):Objects.equals(null, null)将会返回true-请记住这一点。
托马斯

20

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

equals()方法不是为简单类型构建的。简单类型可以与==匹配。


4
支持最有用的实际答案,而不是明显的“ NullPointerException将被返回” herp derp答案。
Volk 2012年

4
foo.equals(null)

如果foo为null会怎样?

您得到一个NullPointerException。


3

如果Object变量为null,则无法对其调用equals()方法,因此对对象引用null进行检查是正确的。


2

如果尝试对空对象引用调用equals,则将引发空指针异常。


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时,将抛出Null Point Exception。

所以我们应该使用==

if(obj == null)

它将比较参考。


2

Object.equals是null安全的,但是请注意,如果两个对象为null,则object.equals将返回true,因此在将object.equals用于比较。

String firstname = null;
String lastname = null;

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

上面的示例代码片段将返回等于!


JavaDoc所述(阅读它们总是很明智的Consequently, if both arguments are null, true is returned. ...:) :)
Thomas

1

因为equal是从Object类派生的函数,所以该函数比较该类的项。如果将其与null一起使用,则将返回false,原因是类内容不为null。另外,==比较对对象的引用。


好吧,结果只能是falseNullPointerException(如果equals未覆盖到不好的地方)。
汤姆(Tom)

1

这是一个例子,str != null但是str.equals(null)当使用org.json

 JSONObject jsonObj = new JSONObject("{field :null}");
 Object field = jsonObj.get("field");
 System.out.println(field != null);        // => true
 System.out.println( field.equals(null)); //=> true
 System.out.println( field.getClass());  // => org.json.JSONObject$Null




编辑: 这是org.json.JSONObject $ Null类:

/**
 * JSONObject.NULL is equivalent to the value that JavaScript calls null,
 * whilst Java's null is equivalent to the value that JavaScript calls
 * undefined.
 */
private static final class Null {

    /**
     * A Null object is equal to the null value and to itself.
     *
     * @param object
     *            An object to test for nullness.
     * @return true if the object parameter is the JSONObject.NULL object or
     *         null.
     */
    @Override
    public boolean equals(Object object) {
        return object == null || object == this;
    }  
}

这里的问题是field.equals(null)返回true。这破坏了常规的Java行为,因此令人困惑。field.equals("null")至少在我看来,它仅适用于。我不知道为什么库开发人员会认为这会很好地支持。
汤姆(Tom)

顺便说一句,您的第一句话有语法问题,目前尚不清楚您的意思。您的意思是“这里是使用org.jsonstr != nullstr.equals(null)返回的示例”?true
汤姆(Tom)

我认为这是因为jsonObject包含“字段”键,这就是为什么field它不为null 的原因,它有一个包含json.org.JSONObject$Null 对象的引用
dina

是的,但我不会把Null喜欢null并会使用"null"来代替。但是我想他们这样做是为了避免使用字符串。但是即使有了这个lib,field.equals(null)仍然几乎总是一个问题:P。
汤姆(Tom)

0

因此,我永远不会感到困惑,并且避免使用此解决方案出现问题:

if(str.trim().length() <=0 ) {
   // is null !
}

5
如果str为null,则将是NPE
typoerrpr

另外,字符串(""长度为0)与null引用完全不同(即,没有字符串)。
托马斯

0

我昨晚遇到过这种情况。
我简单地确定为:

不存在equals()方法
所以,你不能调用一个不存在的方法,如果你没有
- >>>这就是原因,为什么我们使用==检查


0

您的代码违反了得墨meter耳定律。因此,最好重构设计本身。解决方法是,您可以使用Optional

   obj = Optional.ofNullable(object1)
    .map(o -> o.getIdObject11())
    .map(o -> o.getIdObject111())
    .map(o -> o.getDescription())
    .orElse("")

以上是检查对象的层次结构,因此只需使用

Optional.ofNullable(object1) 

如果您只有一个物体要检查

希望这可以帮助 !!!!


-3

你总是可以做

if (str == null || str.equals(null))

这将首先检查对象引用,然后在引用不为null的情况下检查对象本身。


if(str == null || str.equals(null)|| str.equals(“”))
Lou

我用你的答案,并添加了一个空字符串的检查!如果我没记错的话,null和“”不是同一件事。
Lou Morda 2012年

4
添加第二个null检查不是完全多余吗?
Justin Rowe 2014年

2
@JustinRowe这不仅多余,而且非常错误。拜托,不要做类似的事情x.equals(null)
汤姆

@汤姆,JustinRowe请参阅我的回答上面为什么这是不是多余的,也不完全是垃圾 stackoverflow.com/questions/4501061/...
迪那
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.