我怎么能在null对象上调用方法?

时间:2011-12-21 05:23:50

标签: java core

public class JavaPuzzler {

    public static void main(String[] args) {
    JavaPuzzler javaPuzzler = null;
    System.out.println(javaPuzzler.get());
    }

    private static String get(){
        return "i am a java puzzler";
    }
}

您可能认为它应该抛出NullPointerException,因为main方法在局部变量上调用get()方法,该方法已初始化 为null ,并且您无法在null上调用方法。

但是如果你运行这个程序,你会看到它打印出“我是一个java puzzler”。

任何人都可以给我答案。 提前谢谢。

9 个答案:

答案 0 :(得分:6)

在您的代码示例中,get()是属于该类的静态成员,而不是实例。您不需要实例来调用该方法。

public static String get() // belongs globally to class, no instance required
public String get() // belongs to instance

答案 1 :(得分:4)

这是因为该方法是静态的,虽然您引用了一个实例,但实例并不是必需的。 Java语言规范在section 8.4.3.2中解释了原因:

  

声明为static的方法称为类方法。一类   始终在不引用特定对象的情况下调用方法。

这意味着javaPuzzler实例为空是无关紧要的 - 方法“属于”类,而不是实例。

答案 2 :(得分:3)

get方法是静态的,这意味着在该调用中忽略了javaPuzzler中的实际引用,只使用了变量的类型。

答案 3 :(得分:1)

您的方法是静态的。所以它只能以静态方式调用。

所以即使你把它作为javaPuzzler.get(),实际调用将是JavaPuzzler.get(),因此打印!!

答案 4 :(得分:1)

您正在调用静态方法,您不需要实例来调用它,这就是它的工作原理。

答案 5 :(得分:1)

如果我们尝试使用NULL对象调用方法,只要方法不是静态的,它就会抛出NullPointerException

如果方法是静态的,它将运行。

阅读HERE以获取更多参考资料

答案 6 :(得分:1)

像所有人在这里提到的那样,它起作用是因为get()是一种静态方法。以下是您可以考虑的方法:

在Java中定义类时,您实际上要做的是定义对象将保存的数据,以及一组对该数据进行操作的方法。现在,虽然您可以拥有成千上万个对象,但是为每个对象提供所有方法的副本是没有意义的。会发生的是,类存储您定义的方法,并在您调用方法的对象的范围中执行它们。如果您尝试在未初始化的对象上调用这些方法,则该对象仍然存在,并且该方法仍然存在,但它无法使用范围,从而为您提供NullPointerException

此规则的例外是静态方法,它们是不需要范围的方法 - 它们不引用特定于对象的数据。这就是为什么它们可以运行而不管对象是否被初始化。

请记住,对象没有方法的副本......这些方法只是在对象数据的范围内调用。所以你仍然可以访问null(未初始化的)对象的方法,但是非静态方法没有数据可以处理。

答案 7 :(得分:0)

编译器自动将实例调用更改为类调用。如果你有一个反编译器,你可以观察生成的字节码的变化:

...
 public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 8 L0
    ACONST_NULL
    ASTORE 1
   L1
    LINENUMBER 9 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    INVOKESTATIC JavaPuzzler.get()Ljava/lang/String;
    INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
   L2
    LINENUMBER 11 L2
    RETURN
   L3
    LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
    LOCALVARIABLE javaPuzzler LJavaPuzzler; L1 L3 1
    MAXSTACK = 2
    MAXLOCALS = 2
...

答案 8 :(得分:0)

在上面的代码中,你给了get()函数static。静态函数和数据成员不属于任何对象。他们属于这个班级。您可以使用类的对象调用静态函数,但这不是一个好方法,因为它会消耗额外的内存。

自static,JavaPuzzler.get());将为您提供输出而不是空指针异常。

如果get()方法是非静态的,它会给出空指针异常。