【问题标题】:Is null check needed before calling instanceof?在调用 instanceof 之前是否需要检查空值?
【发布时间】:2011-02-26 09:03:55
【问题描述】:

null instanceof SomeClass 会返回false 还是抛出NullPointerException

【问题讨论】:

  • 对于任何旨在仅在非null 相同类型的对象,并在一行中保护您免受“愚蠢的情况”的影响。更少的代码 = 更少的错误。
  • 权衡“这有用吗?”辩论 - 我从未编写过自己的 Java 代码(所以不容易知道规范在哪里,编译测试将非常重要),但我目前正在手动将 Java 转换为 JavaScript。我的代码在空引用上失败了,谷歌搜索让我看到了接受的答案,这证实了这是预期的行为,并且我错过了一个隐式的空检查。对我来说非常有用。

标签: java nullpointerexception null


【解决方案1】:

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

如果xnull,则表达式x instanceof SomeClassfalse

Java 11 语言规范在section 15.20.2, "Type comparison operator instanceof" 中简洁地表达了这一点。 (Java 17 expresses this less concisely,在引入instanceof模式匹配之后。)

"在运行时,结果 instanceof 运算符是 true 如果 RelationalExpression 的值是 不是null,参考可能是 转换为 ReferenceType 没有提出ClassCastException。 否则结果为false。”

所以如果操作数为空,则结果为假。

【讨论】:

  • 这个答案比try it 更正确,因为当前行为保证行为不同。
  • 这个问题在 Joshua Bloch 的 Effective Java - amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683 中关于对象相等的章节中发挥作用
  • 具体来说,在第 8 项中,他指出在 equals() 方法中,一个 instanceof 运算符有两个用途 - 它验证参数是否为非 null 且类型正确。 “...[S]你不需要单独的空检查。”
  • @BenThurley - 过去和现在的 Java 规范都保证了这种行为。我认为卢克的观点解决了实验在确定当前有保证的行为方面的局限性。
  • @GabrielBB 这就像用红笔在红纸上写字一样。即使它没有任何意义,由于将任意笔与任意纸结合起来的一般可能性,它也是可能的。并且在笔中实施“用相同颜色书写”检查会使技术复杂化,而几乎没有任何好处。
【解决方案2】:

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

【讨论】:

  • (现在在 Google 中找到这个问题需要 10 秒)
【解决方案3】:

确实是非常好的问题。我只是为自己尝试。

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. Type Comparison Operator instanceof

在运行时,如果 RelationalExpression 的值不是 null 并且引用可以转换为 ReferenceTypeinstanceof 运算符的结果是 true /em> 没有提出ClassCastException。否则结果为false

API / Class#isInstance(Object)

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

【讨论】:

  • 有点混乱。 s 是字符串,因为它说“字符串 s”,s 不是字符串,因为它为空。那么s到底是什么?
  • @KaiWang s 只是一个对象引用变量。它可能引用一个实际存在的对象(""),也可能引用一个(该)null 文字引用。
  • 我还是一头雾水。 s 现在可能为 null,但以后只能指向 String 实例。它不能像整数一样被指向。所以它仍然是一种字符串,即使它是一个空值。只是没有多大意义......
  • @KaiWang 您将变量类型与实际对象的类型混淆了。变量不是实例;它们实际上只是指针。 null 不是字符串数据,无论指向它的变量是什么。例如,s instanceof Stringfield.getType().equals(String.class) 不同。
  • @KaiWang 你必须想象在调用s instanceof Strings 被替换为实际值,所以会变成"" instanceof Stringnull instanceof String。这样想可能更有意义。
【解决方案4】:

不,不是。如果instanceof 的第一个操作数是null,则instanceof 将返回false

【讨论】:

    【解决方案5】:

    就像一个花絮

    即使(((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。)


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

    【讨论】:

      【解决方案6】:

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

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

      如果操作数是null,则instanceof 运算符返回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");
               }  
      }
      

      【讨论】:

        【解决方案7】:
        • instanceof 之前不需要空检查
        • 在 instanceof 验证为 true 之后,不需要进行 null 检查

        以下是空安全的:

        if(couldbenull instanceof Comparable comp){
           return comp.compareTo(somethingElse);
        }
        
        //java < 14
        if(couldbenull instanceof Comparable){
           return ((Comparable)couldbenull).compareTo(somethingElse);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-06
          • 1970-01-01
          • 2015-09-12
          • 1970-01-01
          • 2021-09-21
          • 1970-01-01
          • 2011-03-08
          • 1970-01-01
          相关资源
          最近更新 更多