2

この単純なプログラムの出力はですThis is base

public class mainApp{
    private void func(){
      System.out.println("This is base"); 
    }

    public static void main(String[] args){
        mainApp newObj = new derived();
        newObj.func();
    }
}

class derived extends mainApp{
    public void func(){ 
      System.out.println("This is derived"); 
    }
}
  • 私の質問は、この行を使用しているときに、基本クラスmainAppの参照を使用して派生mainApp newObj = new derived();クラスのオブジェクトを実際に作成していないかどうかです。それで、オブジェクトを使用してそのメソッドを呼び出すとき、派生クラスからメソッドを取得しないのはなぜですか?基本クラスからメソッドを取得する理由。

  • この行を使用して、 mainAppmainApp newObj = new derived();の参照を操作しているか、派生クラスのオブジェクトを操作していますか。どちらが正しいですか?

4

2 に答える 2

8

基本クラスメソッドを取得する理由は、の基本クラスバージョンfuncが宣言されprivateており、Javaではプライベートメソッドをサブクラスでオーバーライドできないためです。つまり、基本クラスを拡張し、偶然にプライベートメンバー関数に基本クラスのプライベートメンバー関数と同じ名前を付けることにした場合でも、基本クラスのメンバー関数の動作を誤って変更することはありません。実際にタイプのオブジェクトを操作していますがderived、参照は静的にとして型付けされているためmainApp、呼び出しは、のパブリックメソッドではなくプライベートメソッドfuncの呼び出しとして解釈されます。読み取るコードを変更するfuncmainAppfuncderived

derived d = new derived();
d.func();

の静的タイプdは現在derivedであり、への呼び出しfuncの意味が異なるため、これを修正します。

JVMバイトコードレベルでは、プライベートメンバー関数を呼び出すためにinvokespecial使用される命令はですが、通常のオーバーライド可能なメンバー関数を呼び出すために使用される命令はですinvokevirtual。この2つは、まったく異なるセマンティクスを持っています。invokespecial現在のクラス(またはコンストラクターなどの基本クラス)のinvokevirtual検索を開始しますが、実行時にオブジェクトのタイプに対応するクラスを検索します。

于 2011-07-21T21:12:18.243 に答える
0

あなたはderivedクラスで働いています。そのオブジェクトへの参照はmainAppです。つまり、他の人はそれをとして見ますmainAppが、派生クラスとして実装されます。

于 2011-07-21T21:11:53.180 に答える