为什么在空对象上调用此方法不会出现NullPointerException?

10

输出的原因是什么?我知道它会打印Hello World,但不知道为什么,因为它应该会出现NullPointerException

public class Null
{
    public static void greet()
    {
        System.out.println("Hello World");

    }
    public static void main(String[] args)
    {
        ((Null)null).greet();
    }
}
4个回答

7
这是因为greet()是一个静态方法。所以。
((Null)null).greet();

等同于,

Null.greet()

4

greet 是一个静态方法,不需要类实例来调用它。

((Null)null) 表达式不会解引用 null,它只是作为类型定义用于访问这个静态方法。


3
当我们试图使用一个空值的对象引用时,将会抛出NullPointerException异常。因此,在您的示例中,您可能会认为如何从空对象成功调用greet()方法。
但是,仔细看方法签名,发现它有一个static修饰符。如果您在具有空引用的对象上调用静态方法,您将不会得到任何异常,并且代码将正常运行。这是因为静态方法是类方法而不是实例方法。
因此,当您编译代码时,((Null)null).greet()将被简单地转换为Null.greet()
为了简单起见,请参考下面的代码:
Null obj1 = null;
Null obj2 = new Null();
obj1.greet();
obj2.greet();

在这里,greet()是一个静态方法。因此,在调用该方法时,编译器将忽略对象内部是否有任何内容。对于obj1obj2,它将仅编译为Null.greet()

但是,请尝试从该方法中删除static修饰符。你会发现你期望的NullPointerException


3
这是有效的行为,因为:
((Null)null).greet();

调用Null类上的静态方法greet,就像调用一个静态方法一样。在JLS的示例15.11.1-2. Receiver Variable Is Irrelevant For static Field Access中,甚至将其显示为正确行为:

以下程序演示了空引用可以用于访问类(静态)变量而不会导致异常:

class Test3 {
    static String mountain = "Chocorua";
    static Test3 favorite(){
        System.out.print("Mount ");
        return null;
    }
    public static void main(String[] args) {
        System.out.println(favorite().mountain);
    }
}

关于代码编译和输出 "Mount Chocorua" 的解释:

尽管 favorite() 方法的结果是 null,但不会抛出 NullPointerException。打印出 "Mount " 表明主表达式确实在运行时被完全评估,尽管仅使用其类型而非值来确定要访问哪个字段(因为字段 mountain 是静态的)。

因此,在您的情况下,只有 ((Null)null) 这种类型的表达式 - 它被评估为 Null - 用于确定要调用哪个方法(因为在 Null 类中有一个静态方法 greet,所以这不是问题)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接