ChatGPT解决这个技术问题 Extra ChatGPT

在调用 instanceof 之前是否需要检查空值?

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

对于旨在仅在相同类型的非空对象上成功的任何比较或等于或类似方法的“最佳实践”开始(或非常早)行,它也是“重要的”或至少非常有用,并且在一行中保护您免受“愚蠢案例”的侵害。更少的代码=更少的错误。
权衡“这有用吗?”辩论 - 我从未编写过自己的 Java 代码(所以不容易知道规范在哪里,编译测试将非常重要),但我目前正在手动将 Java 转换为 JavaScript。我的代码在空引用上失败了,谷歌搜索让我看到了接受的答案,这证实了这是预期的行为,并且我错过了一个隐式的空检查。非常有用,就我而言。

A
Andy Thomas

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

如果 xnull,则表达式 x instanceof SomeClassfalse

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

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

因此,如果操作数为空,则结果为假。


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

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


(现在在谷歌中找到这个问题需要 10 秒)
J
Jin Kwon

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

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,并且可以将引用强制转换为 ReferenceType 而不会引发 ClassCastException,则 instanceof 运算符的结果为真。否则结果为假。

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。这样想可能更有意义。
L
L Joey

不,这不对。如果第一个操作数是 nullinstanceof 将返回 false


A
Attila Tanyi

就像一个花絮:

甚至 (((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


关于你的 PS:如果有人真的在面试中提供了问题,那么他们太初级了,不能面试。任何问题的正确或错误答案在面试中都不重要。重要的是围绕该主题的随后对话。
L
L Joey

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

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

如果操作数是 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");
         }  
}

M
Marinos An

在 instanceof 之前不需要空检查

在验证为 true 的 instanceof 之后不需要进行空检查

以下是空安全的:

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

T
Tris

不,在调用 instanceof 之前不需要检查 null。如果它的值为 null,它总是返回 false。

根据 Java Language Specification 使用 instanceof 进行比较。

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

因此我们可以推断出 java 也有一个叫做 null 的类型,并且这个 null 类型在 instanceof 运算符中被检查,它显然返回 false,因为它需要一个特定的类型。

Java 编程语言中有两种类型:原始类型和引用类型。根据类型和值的 Java Specification

还有一种特殊的 null 类型,即表达式 null 的类型,它没有名称。因为 null 类型没有名字,所以不可能声明一个 null 类型的变量或强制转换为 null 类型。空引用是空类型表达式的唯一可能值。空引用始终可以进行扩展引用转换为任何引用类型。

从 Java 14 开始,尤其是。在 LTS Java 17 中,我们有一个增强的 instanceof。我们有模式匹配功能,它在类型比较之后执行强制转换。

例子

public static void main(String[] args) {
    Object testObject = "I am a string";
    List<Object> testList = null;
    if (testList instanceof List) {
        System.out.println("instance of list");
    } else {
        System.out.println("null type");
    }
    //Enhanced instanceof with type conversion - tested with JDK 17
    if (testObject instanceof String str) {
        System.out.println(str.toUpperCase());
    }
}

输出

null type
I AM A STRING