2012-01-24 12 views
6

Javaチュートリアルを勉強しているうちに、ReflectionとLate Bindingが私を混乱させました。いくつかのチュートリアルでは、彼らは両方とも同じであり、ReflectionとLate Bindingの間に違いはないと書いています。しかし、他のチュートリアルでは違いがあると言います。リアルタイムでのJavaのリフレクションとレイトバインディングの違い

私は混乱していますので、ReflectionとLate BindingがJavaでどのようなものかを説明してください。可能であれば、両方の現実的な例を教えてください。結合

おかげ..

答えて

2

後期(動的ディスパッチとして知られている)反射を必要としない - それはまだすなわちの署名動的にコンパイル時(でにバインドするためにどのメンバーを知っている必要があります実行時にオーバーライドされたメンバへのバインディングが発生した場合でも、メンバはコンパイル時に認識されます)。はランで起こるすべてのもの - 反射を行う場合

、あなたも、あなたが使用しているメンバー(いなくてもがコンパイル時に知られている、おろか署名を)知りません時間がかかるので、それはずっと遅くなります。

+0

わからないのパフォーマンスは本当に言語のように異なる特徴を比較するときに考慮に入れるための最良の寸法であり、彼らはさまざまな問題を解決することを目指して... –

3

Javaは、多型をサポートするためにレイトバインディングを使用します。つまり、多くのメソッドのどれを使用すべきかの判断は、実行時まで延期されます。

インタフェースの抽象メソッド(または抽象クラスfwiw)を実装するN個のクラスのケースを取り上げます。

public interface IMyInterface { 

    public void doSomething();  
} 

public class MyClassA implements IMyInterface { 

    public void doSomething(){ ... } 
} 

public class MyClassB implements IMyInterface { 

    public void doSomething(){ ... } 
} 

public class Caller { 

    public void doCall(IMyInterface i){ 
     // which implementation of doSomething is called? 
     // it depends on the type of i: this is late binding 
     i.doSomething(); 
    } 
} 

反射は、すなわち、他のコードを検査することができるコードを記述するために代わりに使用されています。どのメソッドや属性がクラスで利用可能かを知り、メソッドを呼び出す(またはクラスをクラスをロードする)ために、実行時に非常に興味深いことをたくさんすることです。

反射の非常に素晴らしいのexplainationはここにある:What is reflection and why is it useful?

2

実世界の例:

あなたはjdesktop 0.9でjdesktop 0.8、しかし船でプロジェクトをビルドする場合は、あなたのコードはまだ、0.9の機能を使用します。レイトバインディングを利用しているため、コンパイルされたバージョンに関係なく、コードが呼び出すコードはクラスローダによってロードされるバージョンです。 (これは、アプリケーションに呼び出されたコードのコンパイル時のバージョンを埋め込むリンカーとは対照的です)。

反映のために、Java 1.5と1.6をターゲットにしようとしていますが、 1.6が利用可能な場合は、JTabbedPaneクラスのリフレクションを使用してsetTabComponentAtメソッドを検索し、存在を確認します。この場合、これらの機能をまったく持っていないJava 1.5に対してビルドしているため、直接呼び出すことはできません。そうしないと、コンパイルが失敗します。しかし、エンドユーザのシステム上で1.6(あなたのところで縛られたものがここに現れます)に反して走っているのであれば、リフレクションを使って1.5に存在しなかったメソッドを呼び出すことができます。

これらは関連しています。リフレクションの多くの使用法は、遅延バインディングに依存することに依存していますが、言語と実装の根本的に異なる側面です。

1

"Late Binding"によって解決される重要な問題の1つは、多態性です。すなわち、クラス階層に沿った適切なオーバーライドされたメソッドの呼び出しは、コンパイル中ではなくランタイム中に決定されます。リフレクションは、実行時にオブジェクトに関する情報を収集し操作する機能です。例えば。実行時に 'Class'属性を使用してオブジェクトのすべての属性またはメソッド名を取得し、それらのメソッドを呼び出すか、その属性を操作できます。

次のコードでは、オブジェクトobj = new MyClass( "MyInstance")などの単純なものを使用するのではなく、リフレクションによって新しいオブジェクトを動的に作成できます(クラスを使用してコンストラクタを取得してアクセスする方法を参照してください)。同様の方法で、他のコンストラクタフォーム、メソッド、および属性にアクセスすることも可能です。 Javaの訪問での反射についての詳細は:http://java.sun.com/developer/technicalArticles/ALT/Reflection/

 

... in some method of some class ... 
Class c = getClass(); 
Constructor ctor = c.getConstructor(String.class); 
Object obj = ctor.newInstance("MyInstance"); 
 
0

私はここで回答のほとんどに同意する必要があります -

誰もがJavaが遅くて、実行時にメソッドの実装上でゼロの面で何を呼び出しますバインディングが、私の意見では、Javaが何をするための用語バインディングを使用するのは正しくありません。

レイトバインディングは、コンパイル時にメソッド呼び出しのチェックが全く行われていないことを意味し、メソッドが存在しない場合はコンパイルエラーは発生しません。

ただし、メソッド呼び出しを修飾する型の型階層のどこかにメソッドが存在しない場合、Javaはコンパイルエラーをスローします(ここでの動作を説明するときは多少近似しています)。これは純粋な伝統的な晩年の結束ではない 通常の非プライベートで非最後の非静的メソッド呼び出しでJavaが行うことは、動的ディスパッチと呼ばれることがあります。
しかし、リフレクションをJavaで使用すると、コンパイラは呼び出されたメソッドが存在するかどうかを単に検証できないため、Javaは純粋なレイトバインディングを実行します。 が次に例を示します。

class A 
{ 
    public void foo() 
    { 
     System.out.println("Foo from A"); 
    } 
} 

class B extends A 
{ 
    public void foo() 
    { 
     System.out.println("Foo from B"); 
    } 
} 
public class C 
{ 
    public static void main(String [] args) 
    { 
     A a=new A(); 
     B b=new B(); 
     A ref=null; 
     Class ref1 = null; 
     ref1 = b.getClass(); 
     ref.foo1();//will not compile because Java in this normal method 
     //call does some compile time checks for method and method 
     //signature existence. NOT late binding in its pure form. 
     try { 
      ref1.getMethod("foo1").invoke(null); //will throw a 
      //NoSuchMethodException at runtime, but compiles perfectly even 
      //though foo1 does not exist. This is pure late binding. 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     } 
} 
関連する問題