Javaランタイムバインド検討の向上


ランタイムバインドは、オブジェクトメソッドを呼び出すメカニズムであるダイナミックバインドとも呼ばれます.Javaがオブジェクトメソッドを呼び出す場合、通常はランタイムバインドメカニズムが採用されます.
1.Javaのメソッド呼び出しプロセス

  • コンパイラは、オブジェクトの宣言タイプとメソッド名(オブジェクト変数の宣言タイプ)を表示します.宣言タイプによってメソッドのリストが見つかります.

  • コンパイラは、呼び出しメソッドを表示するときに提供されるパラメータのタイプを表示します.

  • メソッドがprivate、static、final、またはコンストラクタであれば、コンパイラはそのメソッドを呼び出すことを決定することができます.これは静的バインドです.

  • 上記でない場合は、ランタイム(ダイナミック)バインドを使用します.プログラムの実行時にダイナミックバインドを使用すると、仮想マシンがオブジェクトの実際のタイプに限定されたメソッドを呼び出すことを意味します.

  • 2.ランタイム(動的)バインドのプロセス

  • 仮想マシンがオブジェクトの実際のタイプを抽出する方法テーブル.

  • 仮想マシン検索方法の署名;

  • メソッドを呼び出します.

  • ここでは、オブジェクトの実際のタイプについて説明します.すなわち、マルチステートの場合、仮想マシンは実行されるオブジェクトの真のタイプを見つけることができます.
    3.アップコンバートの場合の動的バインドの例
    public class Father {
        public void method() {
           System.out.println("    ,    :" + this.getClass());
        }
    }
    public class Son extends Father {
        public static void main(String[] args) {
           Father sample = new Son();//    
           sample.method();
        }
    }

    結果:
    親メソッド、オブジェクトタイプ:class samples.Son
    この結果は疑問なく、親クラスの参照(ハンドル)が宣言されていますが、正確に子クラスのオブジェクトが呼び出され、methodが呼び出され、子クラスにはこの方法がないので、親クラスに行って見つけて呼び出されます.
     
    サブクラスを変更し、methodメソッドを書き換えます.
    public class Son extends Father {
        public void method() {
           System.out.println("    ,    :" + this.getClass());
        }
        
        public static void main(String[] args) {
           Father sample = new Son();//    
           sample.method();
        }
    }

    結果:
    サブクラスメソッド、オブジェクトタイプ:class samples.Son
    この結果も予想外だった.methodを呼び出すと、サブクラスでこのメソッドが見つかったので、直接呼び出されます.
    4.静的バインドメンバー変数Javaクラスのメンバー変数を処理する場合、ランタイムバインドではなく、一般的な静的バインドを使用します.したがって、アップグレードの場合、オブジェクトのメソッドはサブクラスを「見つける」ことができ、オブジェクトのプロパティは親のプロパティです.
    さらに変更すると、同じ名前のメンバー変数nameを親と子で同時に定義して付与し、その変数の値を出力しようとします.
    public class Father {
        protected String name="    ";
        
        public void method() {
           System.out.println("    ,    :" + this.getClass());
        }
    }
    public class Son extends Father {
        protected String name="    ";
        
        public void method() {
           System.out.println("    ,    :" + this.getClass());
        }
        
        public static void main(String[] args) {
           Father sample = new Son();//    
           System.out.println("     :"+sample.name);
        }
    }

    結果:
    呼び出されたメンバー:親のプロパティ
    この結果は、子クラスのオブジェクト(親クラスの参照handleによって呼び出される)が親クラスのメンバー変数であることを示します.したがって,実行時(動的)バインドが対象とするカテゴリはオブジェクトの方法にすぎないことを明確にしなければならない.
     
    サブクラスのメンバー変数nameを呼び出そうとしましたが、どうすればいいですか?最も簡単な方法は、このメンバー変数をメソッドgetter形式にカプセル化することです.
    public class Father {
        protected String name = "    ";
     
        public String getName() {
           return name;
        }
     
        public void method() {
           System.out.println("    ,    :" + this.getClass());
        }
    }
    public class Son extends Father {
        protected String name="    ";
        
        public String getName() {
           return name;
        }
        
        public void method() {
           System.out.println("    ,    :" + this.getClass());
        }
        
        public static void main(String[] args) {
           Father sample = new Son();//    
           System.out.println("     :"+sample.getName());
        }
    }

    結果:
    呼び出されたメンバー:息子のプロパティ
    (注:FatherのgetNameを削除すると、コンパイル時に「シンボルgetNameが見つからない」というエラーが発生します)