为啥在空引用上调用(静态)方法不会抛出 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 ,尝试在空对象引用上调用虚拟方法 [重复]
尝试在空对象引用上调用虚拟方法 com.google.firebase.iid.FirebaseInstanceId.getInstanceId()'