在调用instanceof之前是否需要进行null检查?


1354

null instanceof SomeClass返回false还是抛出NullPointerException


对于任何“比较”,“等于”或类似方法(仅设计用于仅对相同类型的非空对象成功的方法),它对于“最佳实践”的开始(或很早)行也“重要”或至少非常有用。单行防止您遇到“愚蠢的案件”。更少的代码=更少的错误。

13
权衡一下“这有用吗?” 辩论-我从未编写过自己的Java代码(因此,不容易知道规范在哪里,并且编译测试将是非常简单的),但是我目前正在手动将Java转换为JavaScript。我的代码在null引用上失败,因此使用谷歌搜索使我看到了可接受的答案,这确认了这是预期的行为,并且我缺少隐式的null检查。对我来说非常有用。
Scott Mermelstein 2013年

Answers:


1838

不,在使用instanceof之前不需要进行空检查。

表达式x instanceof SomeClassfalseif xis null

在Java语言规范的15.20.2节“类型比较运算符instanceof”中

“在运行时,instanceof运算符的结果 是,true如果RelationalExpression 的值不是null,并且引用可以强制转换为ReferenceType 而不会引发ClassCastException。否则,结果是false。”

因此,如果操作数为null,则结果为false。


377
这个答案比try it因为当前行为保证行为不同而更正确。
路加福音

3
这个问题进场的对象平等约书亚布洛赫的章节中Effective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
凯文·梅雷迪思

17
他特别指出,在第8项中,在equals()方法中,一个instanceof运算符有两个作用-验证参数是否为非null且类型正确。“ ... [S] o,您不需要单独的null检查。
安迪·托马斯

2
@BenThurley-Java的instanceof运算符是将近20年前发布的Java 1.0的一部分。现在不大可能以破坏现有代码的方式更改行为,而缺少某些好处却无法弥补巨大的成本。二十年前,如果可以强制转换参数,或者为null参数抛出异常,则可能存在返回true的参数。但是这些定义将需要单独的空检查。
安迪·托马斯

3
@BenThurley-该行为由过去和现在的Java规范保证。我认为卢克的观点解决了确定当前行为的实验限制。
安迪·托马斯

267

使用null引用作为instanceof返回的第一个操作数false


268
(现在需要10秒钟才能在Google中找到此问题)
PL_kolek 2015年

73

确实,这是一个很好的问题。我只是为自己而努力。

public class IsInstanceOfTest {

    public static void main(final String[] args) {

        String s;

        s = "";

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));

        s = null;

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));
    }
}

版画

true
true
false
false

JLS / 15.2.2。类型比较运算符instanceof

在运行时,instanceof运算符的结果是:true如果RelationalExpression的值不是null,并且引用可以强制转换为ReferenceType而不引发ClassCastException。否则结果为false

API / Class#isInstance(Object)

如果此Class对象表示一个接口,true则如果指定Object参数的类或任何超类实现此接口,则此方法返回;否则,该方法返回。否则返回false。如果此Class对象表示原始类型,则此方法返回false


有点令人困惑。s是字符串,因为它说“ String s”,s不是字符串,因为它是null。那到底是什么?
Kai

1
@KaiWang s只是一个对象引用变量。它可以引用实际存在的object(""),也可以引用原null义引用。
Jin Kwon's

我还是很困惑。s现在可能为null,但以后只能指向String实例。不能像整数一样指向它。因此它仍然是一种String,即使它是null。只是没有多大意义...
王凯

@KaiWang您正在将变量类型与实际对象的类型混淆。变量不是实例;它们实际上只是指针。 null不是字符串数据,无论指向哪个变量。 例如s instanceof String,与并不相同field.getType().equals(String.class)
马修阅读了

@KaiWang您必须想象在调用s instanceof String中将sgets替换为实际值,因此它将变为"" instanceof Stringand null instanceof String。这样思考可能更有意义。
TimoTürschmann'18


16

就像一个花絮

甚至还会回来。(((A)null)instanceof A)false


(如果类型转换null看起来令人惊讶,则有时您必须这样做,例如在以下情况下:

public class Test
{
  public static void test(A a)
  {
    System.out.println("a instanceof A: " + (a instanceof A));
  }

  public static void test(B b) {
    // Overloaded version. Would cause reference ambiguity (compile error)
    // if Test.test(null) was called without casting.
    // So you need to call Test.test((A)null) or Test.test((B)null).
  }
}

因此Test.test((A)null)将打印a instanceof A: false。)


PS:如果您正在招聘,请不要将其用作求职面试问题。:D


7

没有。Java文字null不是任何类的实例。因此,它不能是任何类的实例instanceof 将返回一个falsetrue因此<referenceVariable> instanceof <SomeClass>返回,falsereferenceVariablevalue为null时。


5
那个解释听起来像是奇怪的循环……但是我知道你的意思:-)
Kris

@Kris ty的评论我明白了你的意思:)。编辑了一下答案:)。
开发人员MariusŽilėnas17年

1

instanceof运营商并不需要显式的null检查,因为它不会抛出NullPointerException,如果操作数null

在运行时,instanceof如果关系表达式的值不为真,则运算符的结果为true,null并且可以将引用强制转换为引用类型而不会引发类强制转换异常。

如果操作数为null,则instanceof操作符返回false,因此不需要显式的null检查。

考虑以下示例,

public static void main(String[] args) {
         if(lista != null && lista instanceof ArrayList) {                     //Violation
                System.out.println("In if block");
         }
         else {
                System.out.println("In else block");
         }
}

的正确用法instanceof如下所示,

public static void main(String[] args) {
      
         if(lista instanceof ArrayList){                     //Correct way
                  System.out.println("In if block");
         }
            else {
                 System.out.println("In else block");
         }  
}
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.