1

私は複数の場所で最終的なメソッドが早期にバインドされていることを読みましたが、満足のいく理由を提供するものはありません。親クラス参照で呼び出されるfinalメソッドでも、どうしてそんなにcozになるのか疑問です。コンパイラーは、親のnonfinalメソッドと子のfinalメソッドのどちらが呼び出されるかを判断できません。
ご意見をお聞かせください。

class Parent {
    void meth() {
       System.out.println("parent");
}
}

class Child extends Parent {

@Override
final void meth() {
    // TODO Auto-generated method stub
    System.out.println("child");
}

public static void main(String[] args) {
    Parent parent = new Parent();
    Parent child = new Child();
    child.meth();
    parent.meth();
}
}  

上記のコードでは、child(親参照)で呼び出されるメソッドmeth()が最後のメソッドですが、JVMは、呼び出される子または親メソッドと同様に、実行時にメソッドルックアップテーブルを使用する必要があります。

4

2 に答える 2

3

当然のことながら、アーリー バインディングは、参照の静的型が、メソッドが final 指定子を持つクラスである場合にのみ発生します。

于 2012-09-15T00:48:13.210 に答える
1

Java でのバインディングは 2 段階で行われます。コンパイル時に、コンパイラが認識している参照の型を使用して、型階層の最上位のメソッドにメソッドをバインドします。たとえば、Number 型の変数で toString() を呼び出す場合、コンパイラは Object.toString() ではなく Number.toString() またはサブクラスのオーバーライドを呼び出す必要があることを認識します。

次に、実行時にメソッドを呼び出すときに、オブジェクトの実行時の型が調べられ、型階層内で最も具体的なメソッドが検出されて呼び出されます。つまり、上記の Number.toString の場合、オブジェクトが Integer の場合、Integer.toString を見つけて呼び出します。

メソッドが参照/変数の型で final である場合、サブクラスのオーバーライドが存在しないことがわかっているため、この 2 番目のステップはスキップできます。これが、Dima Rudnick が静的型によって意味するものです。繰り返しになりますが、Number.toString が final で、変数が Number 型の場合、呼び出しているメソッドを知るためにランタイム型を調べる必要はありません。

注:この目的のために、継承されたものに依存するのではなく、Object、Number、および Integer のすべてが特定の toString メソッドを持っていると想定しています。

于 2012-09-15T01:05:45.770 に答える