为啥在空引用上调用(静态)方法不会抛出 NullPointerException?

Posted

技术标签:

【中文标题】为啥在空引用上调用(静态)方法不会抛出 NullPointerException?【英文标题】:How come invoking a (static) method on a null reference doesn't throw NullPointerException?为什么在空引用上调用(静态)方法不会抛出 NullPointerException? 【发布时间】:2011-03-18 15:01:48 【问题描述】:

我用 Java 编写了这个程序

public class Why 

  public static void test() 
    System.out.println("Passed");
  

  public static void main(String[] args) 
    Why NULL = null;
    NULL.test();
  


我读到在null 对象上调用方法会导致NullPointerException,但上面的程序没有?为什么是这样?我是不是理解不正确?

【问题讨论】:

Java解释器一加载类就创建了一个静态成员变量,此时也进行了初始化。 既然你正在学习,你应该熟悉编码约定:java.sun.com/docs/codeconv/html/CodeConventions.doc8.html:具体来说,全大写的名称是为常量保留的。 ...虽然我想这可能是您的初衷,因为您可能希望NULL 始终为null,在这种情况下您可能想了解@987654328 @ 关键字以及它对字段与局部变量(以及类和方法)的含义。 在这里你可以找到静态的编译器级别的实现。 ***.com/q/21037406/1686291 我喜欢它Why NULL = null; 【参考方案1】:

test() 是一个static 方法。 static 成员属于该类型,不需要实例即可访问。

static 成员应该通过类型表达式访问。也就是说,你应该这样写:

Why.test(); // always invoke static method on the type it belongs to!

Java 确实允许您通过对象引用表达式访问 static 成员,但是 这是非常误导,因为这不是static成员访问的实际语义。

Why aNull = null; 
aNull.test(); // DO NOT EVER DO THIS!
// invokes Why.test(), does NOT throw NullPointerException

当通过对象引用表达式访问static 成员时,只有引用的声明类型很重要。这意味着:

引用是否实际上是 null 并不重要,因为不需要实例 如果引用不是null,不管对象的运行时类型是什么,没有动态调度!!!

如您所见,在实例成员访问的两点上完全相反。这就是为什么static 成员应该永远以“非static”的方式被访问,因为它给人一种非常误导的外观。

相关问题

Why doesn't Java allow overriding of static methods ?(了解this 至关重要!) Why isn’t calling a static method by way of an instance an error for the Java compiler?

【讨论】:

【参考方案2】:

静态方法不需要对对象的引用。因此,即使对对象的引用为空,您也可以调用它。这就是 main 方法的工作原理。

尝试从对象中删除静态指定以查看空指针异常。

【讨论】:

【参考方案3】:

它是一个静态方法,它允许您在不实例化实例的情况下调用它的方法。

【讨论】:

【参考方案4】:

您应该在 IDE 中打开各种警告。您可能会看到有关以非静态方式访问静态成员的警告。

你可以做类似 (Why)(null).test() 之类的事情,它只是使用 (Why)(null) 来获取类。

【讨论】:

(Why)(null) 不是有效的 Java 语法。正确的语法是((Why) null)。 :-)【参考方案5】:

静态变量和方法与类相关联,而不是与任何对象相关联。类的每个实例共享一个类变量,该变量位于内存中的一个固定位置。

任何对象都可以更改类变量的值,但也可以在不创建类实例的情况下操作类变量,同样适用于静态方法。 更多refer this。

【讨论】:

以上是关于为啥在空引用上调用(静态)方法不会抛出 NullPointerException?的主要内容,如果未能解决你的问题,请参考以下文章

NullPointerException:尝试在空对象引用上调用虚拟方法 findViewById(int)'

致命异常: main ,尝试在空对象引用上调用虚拟方法 [重复]

SearchView 尝试在空引用上调用虚方法

尝试在空对象引用上调用虚拟方法 com.google.firebase.iid.FirebaseInstanceId.getInstanceId()'

NullPointerException 错误尝试在空对象引用上调用虚拟方法错误

AsyncTask +数据库尝试在空对象引用上调用虚拟方法[重复]