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

时间:2013-07-09 19:45:06

标签: java methods nullpointerexception go this

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

type empty struct{}
func (e *empty) Allocated() bool { return e != nil }

(对于可运行的代码,请单击here

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

class Test {
    public boolean Allocated() { return this != null; }
}

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

3 个答案:

答案 0 :(得分:12)

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

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

理论上,finalprivate方法可以放宽此限制 我假设语言设计者选择不一致。 (以及删除final不会是一个重大改变)

答案 1 :(得分:5)

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

首先nilNULL指针不同,有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>