3

私のワークスペースには、Android lib プロジェクトである A、B、および C の 3 つのプロジェクトがあります。

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

A と B の両方が Android デバイスにインストールされています。実行時に、次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);

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

私は多くの明白な(そしていくつかのそれほど明白ではない)トリックを試しましたが、何もうまくいきませんでした. もちろん、btest のメソッドとインターフェイスを調べたり、そのメソッドを呼び出したりすることはできますが、A と B の両方が lib-project C でIまったく同じインターフェイスを参照しているにもかかわらず、単に にキャストすることはできません。I

前もって感謝します!

PS

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

4

3 に答える 3

2

あなたの質問はひどく不明確なので、私はあなたが何を意味しているのかを推測する必要があります.

まず、InterfaceJava にはクラスがないため、次のような意味ではありません。

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

したがって、インスタンスをインターフェイスにキャストすることについて話していると思いcom.package.b.BTestます(それを…と呼びましょう)com.package.i.I

  • Btestとの両方Iが静的にロードされている場合(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);
    

    もちろん問題は、コードが and を動的にロードBTestIたため、静的型がBTestorである変数を記述する方法がないことIです。BTestしたがって、キャストは、そのimplementsをアサートするための回り道を除いて、実際の目的には役立ちませんI

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


繰り返しIますが、 がコードに静的にリンクされている場合は、次のようにすることができます。

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

Iコードに静的にリンクされていない場合、(明らかに)上記I iで宣言することはできず、btest インスタンスのすべての操作にリフレクションを使用する必要があります。反射的に静的型付けを「実行」することはできません。限目。

于 2012-05-13T15:20:40.227 に答える
2

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

于 2012-05-13T16:14:45.163 に答える
0

インターフェイスIはクラスパス上にある必要があります (または、ランタイムによってロード可能である必要があります)。そうしないと、ランタイム例外が発生します。反省しても、この問題を回避することはできません。

于 2012-05-13T15:08:06.987 に答える