7

Go では、ポインターが逆参照されない限り、null ポインターでメソッドを呼び出しても問題ありません。

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

(実行可能なコードについては、ここをクリックしてください)

ただし、Java では、メソッドがメンバー変数を逆参照しない場合でも、null ポインターでメソッドを呼び出すと、null ポインター例外が発生します。

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

この動作が存在する理由を誰かが知っていますか? それが与える利点はありますか?考え?

4

3 に答える 3

12

これは、すべての Java メソッドが仮想であるためです。

を記述するときsomeInstance.Allocated()、ランタイムsomeInstanceは が実際にメソッドをオーバーライドする派生型であるかどうかを確認する必要があります。

理論的には、この制限はfinalorprivateメソッドに対して緩和された可能性があります。
言語の設計者は、一貫性を保つために選択しなかったと思います。(そして、削除finalが重大な変更にならないように)

于 2013-07-09T19:46:41.460 に答える
5

SLaksによる回答は、Java の観点からは優れています。私はJavaについての手がかりを持っていませんが、Goは知っています。これが私の答えです:

まず第一に、ポインターnilと同じではなく、いくつかの基本的な違いがあります。NULL

次に、Go のメソッドは型のインスタンスの一部ではなく、型自体です。つまり、Go は Java のように vtable をオブジェクト内に格納しません。

var e *empty
fmt.Println(e.Allocated())

は…と同じです(…の構文糖衣):

var e *empty
fmt.Println((*empty).Allocated(e)) // This is valid code

従来の「OOP」言語の静的メソッドと同様に、Allocatedのメンバーとしてどのように呼び出されるかに注意してください。*empty

実際に(*empty).Allocatedは、ドット、アスタリスク、および括弧を含む奇妙な表記法を持つ単なる関数名です。

nilレシーバーは別の引数にすぎないため、それがメソッド ディスパッチ メカニズムにとって重要ではないという事実があります。

Go では、ポインターが逆参照されない限り、null ポインターでメソッドを呼び出しても問題ありません。

OK が正当という意味であれば、nil値に対してメソッドを呼び出して逆参照することも問題ありません。コンパイラは文句を言いません - ランタイム パニックが発生するだけです。

于 2013-07-10T08:29:00.480 に答える