题 在调用instanceof之前需要进行空检查吗?


null instanceof SomeClass 返回 false 或扔一个 NullPointerException


1088
2018-06-01 13:53


起源


对于任何只针对相同类型的非null对象成功的Compare或Equals或类似方法,它也是“重要的”或至少非常有用的“最佳实践”开始(或非常早)行,以及在一条线上保护你免受'愚蠢的案件'。更少的代码=更少的错误。
要权衡“这有用吗?”辩论 - 我从来没有编写自己的Java代码(所以不要轻易知道规范在哪里,编译测试会非常重要),但我目前正在手动将Java转换为JavaScript。我的代码在空引用上失败了,谷歌搜索这个让我看到接受的答案,这证实了它是预期的行为,我错过了一个隐式的空检查。在我看来非常有用。 - Scott Mermelstein
这里的答案可以节省时间。阅读所有评论...... - Adrian
>聪明人可以从愚蠢的问题中学到更多,而不是傻瓜可以从明智的答案中学习。 - phi
idownvotedbecau.se/noattempt - Robert Columbia


答案:


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

表达方式 x instanceof SomeClass 是 false 如果 x 是 null

从Java语言规范, 第15.2.2节“类型比较运算符instanceof”

“在运行时,结果    instanceof 运营商是 true 如果   的价值 RelationalExpression  是   不 null 并且参考可以是   投到了 引用类型   没有提高 ClassCastException。   否则结果是 false“。

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


1456
2018-06-01 14:05



这个答案更正确 try it 因为 目前的行为 是不一样的 保证行为。 - Luke
这个问题在约书亚布洛赫关于对象平等的章节中发挥作用 Effective Java  - amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683 - Kevin Meredith
具体来说,在第8项中,他指出在equals()方法中,一个instanceof运算符有两个目的 - 它验证参数是非空的还是正确的类型。 “...... [你]你不需要单独的空检查。” - Andy Thomas
@BenThurley - Java的 instanceof operator是近20年前发布的Java 1.0的一部分。现在以一种破坏现有代码的方式改变行为是不可能的,缺少一些超过巨额成本的好处。二十年前,如果参数可以被强制转换,或者为null参数抛出异常,也许可能存在返回true的参数。但是这些定义需要单独的空检查。 - Andy Thomas
@BenThurley - 过去和现在的Java规范保证了这种行为。我认为卢克的观点解决了实验在确定当前保证行为方面的局限性。 - Andy Thomas


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


237
2018-06-01 13:53



(现在需要10秒才能在Google中找到这个问题) - PL_kolek
@PL_kolek:我是第二个。如果您可以通过Google快速验证,为什么要分散手头的任务?例如,我正处于大规模重构的过程中,我不想在侧面进行测试。 - paulkore
太短。一个好的答案提供了背景和解释。 - david.pfx


确实很好的问题。我只是为自己尝试过。

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.20.2。类型比较运算符instanceof

在运行时,结果 instanceof 运营商是 true 如果是的价值 RelationalExpression 不是 null 并且可以将参考文献投射到 引用类型 没有提高 ClassCastException。否则结果是 false

API / Class#isInstance(Object)

如果这 Class object表示一个接口,此方法返回 true 如果是指定的类或任何超类 Object 参数实现了这个接口;它返回 false 除此以外。如果这 Class object表示基本类型,此方法返回 false


61
2017-07-29 11:55



有点令人困惑。 s是一个String,因为它表示“String s”,s不是String,因为它是null。那到底是什么? - Kai Wang
@KaiWang s 只是一个对象引用变量。它可能引用一个实际存在的对象("")或者它可以引用一个() null 字面参考。 - Jin Kwon
我还是很困惑。 s现在可能为null,但稍后只能指向String实例。它不能指向,如整数。所以它仍然是一种String,即使它是null。只是没有多大意义...... - Kai Wang
@KaiWang您将变量类型与实际对象的类型混淆。变量不是实例;他们实际上只是指针。 null 不是字符串数据,无论指向它的变量是什么。 s instanceof String 是不一样的 field.getType().equals(String.class), 例如。 - Matthew Read
@KaiWang你必须在电话中想象 s instanceof String 该 s 被实际值取代,这样就会变成 "" instanceof String 和 null instanceof String。像这样思考它可能更有意义。 - Timo Türschmann


不,这不对。 instanceof 会回来的 false 如果它的第一个操作数是 null


23
2018-06-01 13:53





没有。 Java文字 null 不是任何类的实例。因此它不可能是一个 的instanceof 任何课程。 instanceof  将返回 false 要么 true 因此 <referenceVariable> instanceof <SomeClass> 回报 false 什么时候 referenceVariable value为null。


5
2018-05-27 10:59



那个解释听起来很奇怪...但我知道你的意思:-) - Kris
@Kris ty评论我明白了你的意思:)。编辑了一个答案:)。 - Willmore
与问题无关,但它在语义上很奇怪 null instanceof Void 返回false xD - Jai


instanceof 运算符不需要显式 null 检查,因为它没有抛出 NullPointerException 如果操作数是 null

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

如果操作数是 nullinstanceof 操作员返回 false 因此,不需要显式空检查。

考虑下面的例子,

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");
         }  
}

2
2018-04-01 08:09





就像一个 珍闻

甚至 (((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.a(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。)


P.S。:如果您正在招聘,请不要将此作为面试问题使用。 :d


2
2018-03-22 12:11