我的工作区中有3个项目--A,B和C,这是一个Android lib项目。
Atest
Btest
的类,它实现了接口I
。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);
现在这是我的问题 - 有没有办法在I
运行上下文中将btest转换为A
?
我尝试了许多明显的(以及一些不那么明显的)技巧,但对我来说没有任何效果。我当然可以探索btest的方法和接口,调用它的方法等等。但我根本无法将它转换为I
,尽管A和B都引用了lib中完全相同的I
接口-project C。
提前致谢!
P.S。
请注意,我将其投射到界面中,而不是放入对象中,因此我认为在这种情况下不同的ClassLoader
不是原因。
答案 0 :(得分:1)
你的问题非常不明确,所以我不得不猜测你的意思。
首先,Java中没有Interface
类,所以你不能这样说:
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);
问题当然是因为您的代码已动态加载BTest
和I
,所以无法编写静态类型为BTest
或I
的变量。所以演员阵容没有任何实际意义,除了作为断言BTest
实施I
的圆周方式。
另一种可能性是你在讨论如何转换类对象。但鉴于您必须使用通配符作为Class
的类型参数,这没有任何意义。
重申一下,如果I
静态链接到您的代码中,那么您可以这样做:
Object btest = // create or retrieve the instance reflectively
I i = (I) btest;
如果I
没有静态链接到您的代码中,那么您(显然)不能在上面声明I i
,并且您必须对btest实例中的所有操作使用反射。你不能反思地“做”静态打字。周期。
答案 1 :(得分:1)
因为您在运行时执行所有此动态加载,所以不构造虚拟方法表及其关联的vpointers。因此,运行时无法动态地将对接口方法的调用分派给适当加载的实现。你必须使用反射。
答案 2 :(得分:0)
接口I
必须位于类路径上(或者可由运行时加载),否则您将获得运行时异常。反思不会让你避免这个问题。