在Go中,可以在空指针上调用方法,只要该指针永远不会被解引用:
type empty struct{}
func (e *empty) Allocated() bool { return e != nil }
(对于可运行的代码,请单击here)
但是,在Java中,调用空指针上的方法,即使该方法从不取消引用任何成员变量,仍会导致空指针异常:
class Test {
public boolean Allocated() { return this != null; }
}
有人知道为什么会出现这种行为吗?它有一些优势吗?想法?
答案 0 :(得分:12)
这是因为所有Java方法都是虚拟的。
当您编写someInstance.Allocated()
时,运行时需要检查someInstance
是否实际上是覆盖该方法的派生类型。
理论上,final
或private
方法可以放宽此限制
我假设语言设计者选择不一致。 (以及删除final
不会是一个重大改变)
答案 1 :(得分:5)
从Java角度来看, SLaks 的答案是好的。我对Java没有任何线索,但我知道Go,这是我的答案:
首先nil
与NULL
指针不同,有some fundamental differences。
然后,Go中的方法不是类型实例的一部分,而是类型本身,即Go不会将vtable存储在对象内部,就像Java那样:
var e *empty
fmt.Println(e.Allocated())
与...相同(...的语法糖):
var e *empty
fmt.Println((*empty).Allocated(e)) // This is valid code
请注意Allocated
作为*empty
成员的调用方式,非常类似于传统“OOP”语言中的静态方法。
实际上,(*empty).Allocated
只是一个函数名称,带有一个奇怪的符号,包括一个点,一个星号和一个parens。
因为接收器只是另一个参数,所以它是nil
这一事实对于方法调度机制并不重要。
在Go中,可以在空指针上调用方法,只要该指针永远不会被解引用
如果确定你的意思是合法的,那么在nil
值上调用方法并解除引用它甚至可以。编译器不会抱怨 - 你只会遇到运行时恐慌。
答案 2 :(得分:-2)
我认为这是一个哲学问题;方法(静态方法除外)将应用于一个对象,就其性质而言,在像“null”这样的非对象上调用这样的方法在这个范例中没有意义。如果你想定义一个可以应用于一个对象或“null”的方法,那么定义一个静态方法就足够了,在我看来,这会使调用该方法的代码不那么容易让读者感到困惑。 / p>