Javaの静的バインディングと動的バインディングのサンプルコードの詳細な説明

伊谢尔伦
リリース: 2017-07-17 16:11:07
オリジナル
1655 人が閲覧しました

Java の静的バインディングと動的バインディング

プログラム バインディングの概念:

バインディングは、メソッド呼び出しと、メソッドが配置されているクラス (メソッド本体) の関連付けを指します。 Java の場合、バインディングは静的バインディングと動的バインディング、または初期バインディングと遅延バインディングに分けられます。コンパイル プロセスでは、このメソッドがどのクラスにあるかはすでにわかっており、この時点でコンパイラまたは他のリンカによって実装されます。例: C.

Java の場合、これは単にプログラムのコンパイル中のバインディングとして理解できます。ここで特別な注意事項があります。Java では、final、static、private、およびコンストラクター メソッドのみが事前にバインドされます

動的バインディング:


遅延バインディング: 実行時の特定のオブジェクトのタイプに基づいたバインディング。

言語が遅延バインディングを実装する場合、実行時にオブジェクトの型を決定し、それぞれ適切なメソッドを呼び出す何らかのメカニズムも提供する必要があります。つまり、この時点ではコンパイラはまだオブジェクトの型を認識していませんが、メソッド呼び出しメカニズムはそれ自体で調査して、正しいメソッド本体を見つけることができます。言語が異なれば遅延バインディングの実装方法も異なります。しかし、少なくとも次のように考えることができます。それらはすべて、何らかの特別な種類の情報をオブジェクトに配置する必要があるということです。

動的バインディングのプロセス:


仮想マシンはオブジェクトの実際の型のメソッドテーブルを抽出します。

メソッドシグネチャを検索します。方法。
  1. finalメソッド、staticメソッド、privateメソッド、コンストラクターメソッドが事前バインドされているという理解について
  2. privateメソッドに関しては、まず継承できないので、経由で呼び出す方法がありません。そのサブクラスのオブジェクトであり、このクラス自体のオブジェクトを通じてのみ呼び出すことができます。したがって、プライベート メソッドは、このメソッドを定義するクラスにバインドされていると言えます。

  3. finalメソッドは継承できますが、オーバーライド(オーバーライド)することはできません。サブクラスオブジェクトは呼び出すことができますが、親クラスで定義されたfinalメソッドが呼び出されます(これにより、メソッドの宣言方法がわかります)。これは最終的なタイプであり、第一にメソッドの上書きを防止し、第二に Java の動的バインディングを効果的に無効にするためのものです。

    コンストラクターは継承できません(インターネット上では、サブクラスは親クラスのパラメーターなしのコンストラクターを独自のコンストラクターとして無条件に継承するとも言われていますが、サブクラスが super() Call を使用していることがわかっているため、この記述は個人的には適切ではないと考えています親クラスのパラメータなしのコンストラクターを使用して親クラスの初期化を完了する必要はありません。したがって、サブクラスが親クラスのコンストラクターを継承するとは言えません。そのため、コンパイルすることができます。また、このコンストラクターがどのクラスに属しているかもわかります。

静的メソッドについては、具体的な原理を明確に説明することができません。しかし、インターネット上の情報と私自身の実験に基づいて、静的メソッドはサブクラスに継承できますが、サブクラスによってオーバーライド(オーバーライド)することはできませんが、サブクラスによって隠蔽することはできると結論付けることができます。 (これは、親クラスに静的メソッドがあり、そのサブクラスに対応するメソッドがない場合、サブクラス オブジェクトがこのメソッドを呼び出すときに、親クラスのメソッドが使用されることを意味します。また、それがサブクラス 同じメソッドがサブクラスで定義されたメソッドを呼び出します。唯一の違いは、サブクラス オブジェクトが親クラス オブジェクトに変換されると、サブクラスで定義されているかどうかに関係なく、オブジェクトは親クラスの静的メソッドを使用することです。 . 静的メソッド したがって、静的メソッドは、親クラスのメンバー変数を非表示にすることはできますが、サブクラス オブジェクトが変換された後のことと同じです。親クラスのオブジェクトにアクセスすると、非表示にすることができます。親クラスの非表示の変数とメソッドにはアクセスできますが、親クラスのオーバーライドされたメソッドにはアクセスできません)


上記のことから、メソッドを継承できない場合、または継承後にオーバーライドできない場合は、このメソッドが使用されます。静的バインディング。


Javaのコンパイルと実行



Javaのコンパイルプロセスは、Javaソースファイルをバイトコード(jvm実行可能コード、つまり.classファイル)にコンパイルするプロセスです。このプロセスでは、Javaはメモリを扱いません。 , このプロセス中に、コンパイラーは構文を分析し、構文が間違っている場合はエラーを報告します。


Java の実行プロセスとは、バイトコード ファイルをロードし、実行のために解釈する jvm (Java 仮想マシン) を指します。このプロセスでは、実際にメモリレイアウトが作成され、Java プログラムが実行されます。
Java バイトコードを実行するには 2 つの方法があります: (1) ジャストインタイム コンパイル方式: インタプリタがまずバイトをマシン コードにコンパイルし、次にマシン コードを実行します。 (2) インタープリタ実行方式: インタプリタが各インタープリタを渡します。そして、小さなコードを実行して、Java バイトコード プログラムのすべての操作を完了します。 (ここでは、Java プログラムが実行中に実際に 2 回変換されることがわかります。最初はバイトコードに、次にマシンコードにです。これが、Java を 1 回コンパイルすればどこでも実行できる理由です。対応する Java 仮想マシンをインストールすることで、異なるプラットフォーム上でも同じバイトコードは、異なるプラットフォームで実行できるように、異なるプラットフォーム上のマシンコードに変換できます)

前に述べたように、Java のメソッドについては、final を除き、事前にバインドされている静的メソッド、プライベートメソッド、およびコンストラクターメソッドを除き、その他すべてのメソッドを除きます。メソッドは動的にバインドされます。
動的バインディングは通常、親クラスとサブクラスの変換宣言の下で発生します:

例: Parent p = new Children();

具体的なプロセスの詳細は次のとおりです:

1: コンパイラチェック 宣言された型およびオブジェクトのメソッド名。

x.f(args) メソッドを呼び出し、x がクラス C のオブジェクトとして宣言されているとします。コンパイラーは、クラス C 内の f という名前のメソッドと、クラス C メソッドのスーパークラスから継承された f という名前のメソッドをすべて列挙します。

2: 次に、コンパイラーはメソッド呼び出しで提供されたパラメーターの型をチェックします。

f という名前のすべてのメソッドの中に、呼び出しによって提供されたパラメーターの型に最も一致するパラメーターの型が存在する場合、このメソッドが呼び出されます。このプロセスは「オーバーロード解決」と呼ばれます。

3: プログラムの実行中に動的バインディングを使用してメソッドが呼び出される場合、仮想マシンは、x が指すオブジェクトの実際の型と一致するバージョンのメソッドを呼び出す必要があります。

実際の型が D (C のサブクラス) であると仮定します。クラス D が f(String) を定義している場合、このメソッドが呼び出されます。それ以外の場合、メソッド f(String) は D のスーパークラスで検索されます。の上。
JAVA 仮想マシンがクラス メソッド (静的メソッド) を呼び出すとき、オブジェクト参照のタイプ (通常はコンパイル時に判明) に基づいて呼び出されるメソッドが選択されます。逆に、仮想マシンがインスタンス メソッドを呼び出すときは、オブジェクトの実際の型 (実行時にのみ知ることができます) に基づいて呼び出されるメソッドが選択されます。これは、ポリモーフィズムの一種である動的バインディングです。 。動的バインディングは、実際のビジネス上の問題を解決するための優れた柔軟性を提供し、非常に美しいメカニズムです。

メソッドとは異なり、Java クラスでメンバー変数 (インスタンス変数とクラス変数) を扱う場合、実行時バインディングは使用されませんが、一般的な意味での静的バインディングが使用されます。したがって、上向き変換の場合、オブジェクトのメソッドはサブクラスを見つけることができますが、オブジェクトの属性 (メンバー変数) は依然として親クラスの属性です (サブクラスは親クラスのメンバー変数を隠します)。


public class Father { 
  protected String name = "父亲属性"; 
}   
public class Son extends Father { 
  protected String name = "儿子属性"; 
  
  public static void main(String[] args) { 
    Father sample = new Son(); 
    System.out.println("调用的属性:" + sample.name); 
  } 
}
ログイン後にコピー

結論、呼ばれたメンバーは父親の属性です。

この結果は、サブクラスのオブジェクト(親クラスからの参照ハンドル)が親クラスのメンバ変数を呼び出していることを示しています。したがって、ランタイム (動的) バインディングの範囲はオブジェクトのメソッドのみであることを明確にする必要があります。

今、サブクラスのメンバー変数名を呼び出そうとしているのですが、どうすればよいでしょうか?最も簡単な方法は、メンバー変数をゲッター メソッドにカプセル化することです。
コードは次のとおりです:


public class Father { 
  protected String name = "父亲属性"; 
  public String getName() { 
    return name; 
  } 
}   
public class Son extends Father { 
  protected String name = "儿子属性"; 
  public String getName() { 
    return name; 
  } 
  public static void main(String[] args) { 
    Father sample = new Son(); 
    System.out.println("调用的属性:" + sample.getName()); 
  } 
}
ログイン後にコピー

結果: プロパティの静的バインディング メソッドのため、息子のプロパティは

Java と呼ばれます。これは、静的バインディングには、実行時ではなくコンパイル時にプログラム内のエラーを検出できるため、多くの利点があります。これにより、プログラムの実行効率が向上します。

以上がJavaの静的バインディングと動的バインディングのサンプルコードの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート