3

我的工作区中有 3 个项目 - A、B 和 C,这是一个 Android lib 项目。

  1. A 包含一个名为Atest
  2. B 包含一个名为Btest实现接口的类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

提前致谢!

附言

请注意,我将其转换为接口,而不是对象,所以我猜ClassLoader在这种情况下,不同不是原因。

4

3 回答 3

2

你的问题非常不清楚,所以我将不得不猜测你的意思。

首先,Java 中没有Interface类,所以你不能这样说:

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

因此,我假设您正在谈论将 INSTANCE ofcom.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);
    

    问题当然是因为你的代码已经动态加载了BTestand I,所以没有办法编写静态类型为BTestor的变量I。所以演员表没有真正的目的,除了作为一种迂回的方式来断言BTestimplements I

另一种可能性是您在谈论强制转换 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 回答