2012-05-13 9 views
1

私は自分のワークスペースに3つのプロジェクトを持っています.A、B、CはAndroidのlibプロジェクトです。取得したClassオブジェクトを(リフレクトを介して)インターフェイスにキャストすることは可能ですか?

  1. AはAtest
  2. Bという名前のアクティビティが含まれ、インターフェイスIを実装Btestという名前のクラスを含んでいます。
  3. Cには、Iインターフェイスが含まれています。

AndroidデバイスにAとBの両方がインストールされています。 Atest実行時に は、私は次のコードを実行している:今ここに

Context otherContext = createPackageContext("com.package.b", 
       CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY); 
ClassLoader loader = otherContext.getClassLoader(); 
Class<?> btest = Class.forName("com.package.b.BTest", true, loader); 

を、私の質問です - A実行コンテキスト内IにBTESTをキャストする方法はありますか?

私は多くの明白な(そしていくつかのそれほど明白ではない)トリックを試みましたが、何も私のために働いていませんでした。 AとBの両方が、LIB-プロジェクトCに

を正確に同じIインタフェースを参照するが、私はのコースなど、そのメソッドを呼び出し、BTESTのメソッドとのインターフェースを探索することができます..しかし、私は単にIにそれをキャストすることはできません前もって感謝します!

P.S.

私はオブジェクトにではなくインターフェイスにキャストしようとしていることに注意してください。この場合、別のClassLoaderはこの理由ではありません。

答えて

1

実行時にこの動的ロードをすべて実行しているので、仮想メソッドテーブルとそれに関連付けられたvpointerが構築されていません。したがって、ランタイムが呼び出しをインタフェースメソッドに動的に適切にロードされた実装にディスパッチする方法はありません。リフレクションを使用する必要があります。

+0

シンプルでとてもクリアです。 "invoke"を介してオブジェクトメソッドにアクセスするエスケープはありますか?私は反射を介してそのオブジェクトにアクセスする必要があります... – avimak

0

インターフェイスIはクラスパス上になければなりません(そうでなければ実行時にロード可能)。そうしないと、実行時例外が発生します。再選ではこの問題を回避することはできません。

+0

'A'は' C'にリンクされているので、 'I'はクラスパス上にあると思います。 – avimak

+0

はい、 'C'が使用可能なクラスであれば、これは' I'がロード可能であることを意味します。あなたは正確に何をしようとしていますか? –

+0

私は 'Btest'を' I'として参照したいと思います。私はそれをオブジェクトまたはクラス /クラスオブジェクトとしてのみ参照することができます。つまり、実装されたインターフェイスメソッドを直接呼び出すことはできませんが、 "invoke"を使用することができます。今はっきりしていますか? – avimak

1

あなたの質問は非常に不明なので、私はあなたが何を意味するか推測する必要があります。

まず、Javaで何Interfaceクラスが存在しないので、あなたはこれを意味することはできません:だから

Interface<?> i = // some magic transformation of btest 

、私はあなたがインターフェイスにcom.package.b.BTestのインスタンスをキャストについて話していると推定(さんがそれを呼びましょう。 ..)com.package.i.IBtestIの両方が静的にロードされている場合は

  • 、そして(I) bTestInstanceは仕事をしていません。

  • Btestが動的にロードされている場合は

    、およびBtest道具Iは、次の作業をする必要があります:

    Class<?> btestCls = Class.forName("com.package.b.BTest", true, loader); 
        // This will work, because I has to be on the classpath of 'loader' 
        // for the previous load to work ... 
        Class<?> iCls = Class.forName("com.package.i.I", true, loader); 
    
        Object btest = // create a BTest instance reflectively 
        Object i = iCls.cast(btest); 
    

    もちろんの問題は、あなたのコードが動的にBTestIロードしているため、書き込みをする方法はありませんということです静的型がBTestまたはIの変数です。だからキャストは、BTestIを実装していると主張するラウンド方法を除いて、本物の目的を果たさない。

もう1つの可能性は、クラスオブジェクトのキャストについて話していたことです。ただし、Classの型パラメータとしてワイルドカードを使用する必要がある場合、それは意味をなさない。


だけIを静的あなたのコードにリンクされている場合、あなたはこれを行うことができ、繰り返しに:Iを静的あなたのコードにリンクされていない場合

Object btest = // create or retrieve the instance reflectively 
I i = (I) btest; 

、あなたは(明らかに)宣言することはできませんI i上では、btestインスタンスのすべての操作に対してリフレクションを使用する必要があります。静的な入力を反映することはできません。期間。

+0

なぜ不明な点がありますか?私はリフレクションを介してオブジェクトを取得しています。これは 'I'インタフェースを実装するオブジェクトです。実行コンテキストで' Class'オブジェクトではなく 'I'として参照し、呼び出しをスキップしてアクセスします「A」と「B」の両方がアクセスしていることを知っているインターフェースを介してそのデータを受け取る。 'B'文脈で走っている間に、' Btest'を 'I'にキャストできます。これは' A'文脈で実行している間に達成しようとしているものです。 – avimak

+0

"これはクラスオブジェクトではなく、私の実行コンテキストにあります。"これは明確ではありません。クラスオブジェクトと 'I'を実装するオブジェクトは全く異なります。 –

+0

"Iを実装するクラスオブジェクトとオブジェクトは完全に異なっています";もちろん。私が意図したことは、Object obj = btest.newInstance()を呼び出してobjを 'I'にキャストすることです。私はあなたに奇妙に聞こえる理由を理解していない - 私はそのオブジェクトにアクセスすることはできませんが、反射を使用しているので、objを既知のインターフェースである「I」にキャストし、私はすべてのそれらから '私は'メソッドを呼び出すことによって呼び出しを呼び出す。今はっきりしていますか? – avimak

関連する問題