为什么不能在Java中调用空指针上的方法?

jos*_*hlf 7 java methods this nullpointerexception go

在Go中,可以在空指针上调用方法,只要该指针永远不会被解引用:

type empty struct{}
func (e *empty) Allocated() bool { return e != nil }
Run Code Online (Sandbox Code Playgroud)

(对于可运行的代码,请单击此处)

但是,在Java中,调用空指针上的方法,即使该方法从不取消引用任何成员变量,仍会导致空指针异常:

class Test {
    public boolean Allocated() { return this != null; }
}
Run Code Online (Sandbox Code Playgroud)

有人知道为什么会出现这种行为吗?它有一些优势吗?思考?

SLa*_*aks 12

这是因为所有Java方法都是虚拟的.

在编写时someInstance.Allocated(),运行时需要检查是否someInstance实际上是覆盖该方法的派生类型.

理论上,这种限制可以放宽finalprivate方法.
我假设语言设计者选择不一致.(以便删除final不会是一个突破性的变化)


thw*_*hwd 5

从Java的角度来看,SLaks的答案很好.我对Java没有任何线索,但我知道Go,这是我的答案:

首先nilNULL指针不一样,有一些根本的区别.

然后,Go中的方法不是类型实例的一部分,而是类型本身,即Go不会将vtable存储在对象内部,就像Java一样:

var e *empty
fmt.Println(e.Allocated())
Run Code Online (Sandbox Code Playgroud)

与...相同(...的语法糖):

var e *empty
fmt.Println((*empty).Allocated(e)) // This is valid code
Run Code Online (Sandbox Code Playgroud)

注意如何Allocated作为成员调用*empty,就像传统的"OOP"语言中的静态方法一样.

实际上,(*empty).Allocated它只是一个带有奇怪符号的函数名称,包括一个点,一个星号和一个parens.

因为接收器只是另一个参数,所以它对nil方法调度机制来说并不重要.

在Go中,可以在空指针上调用方法,只要该指针永远不会被解引用

如果确定你的意思是合法的,那么甚至可以在一个nil值上调用一个方法并取消引用它.编译器不会抱怨 - 你只会遇到运行时恐慌.