9

関連する名前が多すぎます: Early Binding と Late Binding、Static と Dynamic Dispatch、Runtime と Compile-time Polymorphism など、違いがわかりません。

明確な説明を見つけましたが、それは正しいですか? JustinCを言い換えます。

バインディング:変数 (オブジェクト?) の型を決定しています。コンパイル時に行われる場合は、早期バインディングです。実行時に行われる場合は、遅延バインディングです。

ディスパッチ:メソッド呼び出しに一致するメソッドを決定しています。静的ディスパッチはコンパイル時にメソッドを計算しますが、動的ディスパッチは実行時にそれを行います。

Binding は、プリミティブ変数と参照変数をそれぞれプリミティブ値とオブジェクトに一致させていますか?

編集:これについてもっと読むことができるように、明確な参考資料を教えてください。

4

3 に答える 3

6

混乱は通常、これらの用語がどれほど過負荷であるかに起因すると思います.

私たちはプログラムを高水準言語でプログラミングし、コンパイラまたはインタープリターのいずれかがそれを機械が実際に理解できるものに変換する必要があります。

大雑把に言えば、メソッド コードを何らかの形式のマシン コードに変換するコンパイラを思い浮かべることができます。その時点で、後でプログラムを実行するときにそのメソッドがメモリ内のどこにあるかをコンパイラが正確に知っていれば、このコンパイル済みメソッドのすべてのメソッド呼び出しを安全に見つけて、コンパイル済みコードが存在するこのアドレスへのジャンプに置き換えることができます。ありますよね?

ええと、この関係を具体化することは、私が拘束力があると理解していることです. ただし、このバインディングは、言語の設計に応じて、コンパイル時、リンク時、ロード時、または実行時など、さまざまな時点で発生する可能性があります。

静的および動的という用語は、通常、実行前および実行時にそれぞれバインドされるものを指すために使用されます。

結合時間が遅いほど柔軟性が高くなり、結合時間が早いほど効率が高くなります。言語設計者は、言語を作成するときに、これら 2 つの側面のバランスを取る必要があります。

ほとんどのオブジェクト指向プログラミング言語は、サブタイプ ポリモーフィズムをサポートしています。これらの言語では、その時点でのオブジェクトの動的タイプに応じて、実行時に仮想メソッドがバインドされます。つまり、仮想メソッドの呼び出しは、静的な型参照だけに基づくのではなく、関連するオブジェクト実装の動的な型に基づいて、実行時に適切な実装にディスパッチされます。

したがって、私の意見では、まずメソッド呼び出しを特定の実装または実行アドレスにバインドする必要があります。その後、呼び出しをそれにディスパッチできます。

過去に非常によく似た質問に答えたことがあります。その中で、これが Java でどのように発生するかを例で示しました。

プログラミング言語プラグマティクスという本を読むこともお勧めします。理論的な観点からこの種のことをすべて学ぶことは大きな参考になります.

于 2017-01-07T22:52:41.353 に答える
2

「低レベル」の定義を探している場合、おそらく唯一の正当な情報源は、古くからの友人である JLS です。この場合、明確な定義はありませんが、各用語を使用するコンテキストで十分かもしれません。

急送

この用語は、呼び出すメソッドを決定する手順で実際に言及されています。

15.12.2. コンパイル時のステップ 2: メソッド シグネチャの決定

2 番目の手順では、メンバー メソッドの前の手順で決定された型を検索します。このステップでは、メソッドの名前と引数式を使用して、アクセス可能適用可能なメソッド、つまり、指定された引数で正しく呼び出すことができる宣言を見つけます。

そのような方法が複数ある場合があります。その場合、 最も具体的な方法が選択されます。最も具体的なメソッドの記述子 (署名と戻り値の型) は、メソッドのディスパッチを実行するために実行時に使用されるものです。厳密な呼び出しのいずれかで適用可能な場合、メソッドは適用可能です

「最も具体的な」方法とは何かについての詳細は、15.12.2.5 最も具体的な方法の選択で行われます。

「ダイナミックディスパッチ」に関しては、

JLS 12.5。新しいクラス インスタンスの作成:

C++ とは異なり、Java プログラミング言語は、新しいクラス インスタンスの作成中にメソッド ディスパッチの変更されたルールを指定しません。初期化されるオブジェクトのサブクラスでオーバーライドされるメソッドが呼び出されると、新しいオブジェクトが完全に初期化される前であっても、これらのオーバーライド メソッドが使用されます。

それが含まれています

例 12.5-2。インスタンス作成中の動的ディスパッチ

class Super {

  Super() {
      printThree();
  }

  void printThree() {
      System.out.println("three");
  }
}

class Test extends Super {

  int three = 3;

  void printThree() {
      System.out.println(three);
  }

  public static void main(String[] args) {
      Test t = new Test();
      t.printThree();
  }
}

出力:

0
3

これは、コンストラクターの呼び出しチェーン中に のコンストラクターが を呼び出しているために発生しSuperますprintThreeが、動的ディスパッチにより のメソッドTestが呼び出され、それはフィールドが初期化される前です。

バインディング

この用語は、クラス メンバー アクセスのコンテキストで使用されます。

例 15.11.1-1。フィールド アクセスの静的バインドでは、事前バインディングと遅延バインディングが示されています。怠惰な私たちのために、そこに示されている例を要約します。

class S {
    int x = 0;
    int z() { return x; }
}

class T extends S {
    int x = 1;
    int z() { return x; }
}

public class Test1 {

    public static void main(String[] args) {
        S s = new T();
        System.out.println("s.x=" + s.x);
        System.out.println("s.x=" + s.z());
    }
}

出力:

sx=0
sx=1

フィールドは「事前バインディング」を使用し、インスタンス メソッドは「遅延バインディング」を使用することを示します。

このフィールド アクセスの動的ルックアップの欠如により、プログラムを簡単な実装で効率的に実行できます。レイト バインディングとオーバーライドの機能を利用できますが、それはインスタンス メソッドが使用されている場合のみです。

バインディングは、ジェネリックの型の決定に関しても使用されます。

8. クラス

クラスはジェネリック(§8.1.2) である場合があります。つまり、クラスの異なるインスタンス間でバインディングが異なる可能性がある型変数を宣言する場合があります。

List<String>の 2 つのインスタンスを作成すると、両方のインスタンスの のバインディングStringが互いに異なることを意味します。

これは raw タイプにも適用されます。

4.8. 生の型

class Outer<T>{
    T t;
    class Inner {
        T setOuterT(T t1) { t = t1; return t; }
    }
}

Inner のメンバーの型は、Outer の型パラメーターによって異なります。Outer が raw の場合、T の有効なバインドがないため、Inner も raw として処理する必要があります。

つまり、宣言Outer outer(これは生の型の警告を生成します) では型を判別できませんT(明らかに、宣言では定義されていません)。

于 2017-01-07T23:06:00.027 に答える
0

これらは一般的な用語であり、次のように要約できます: あるもの (メソッドまたはオブジェクト) が静的/早期である場合、それはコンパイル時に構成され、実行時にあいまいさがないことを意味します。たとえば、次のコード:

class A {
    void methodX() {
    System.out.print("i am A");
    }
 }

A のインスタンスを作成して methodX() を呼び出すと、野心的なものは何もなく、コンパイル時にすべてが構成されますが、次のコードがある場合

class B extends A {
  void methodX() {
    System.out.print("i am B");
   }
 }
....
A objX= new B();
objX.methodX();

メソッド x の出力は実行時までわからないため、このメソッドは動的にバインド/ディスパッチされます (メソッドリンクのバインドの代わりにディスパッチという用語を使用できます)。

于 2017-01-07T20:02:18.987 に答える