我该怎么做:
class Foo {
public static Foo get() throws Exception {
ClassLoader cl = new URLClassLoader(new URL[]{"foo.jar"}, null); // Foo.class is in foo.jar
return (Foo)cl.loadClass("Foo").newInstance(); // fails on class cast
}
}
我需要的是让JVM从cl中考虑Foo实例,就好像它是来自执行代码的类加载器的Foo实例一样。
我见过这些方法,对我来说都没有好处(上面的例子是一个玩具示例):
答案 0 :(得分:25)
不可能。类标识由完全限定名称和类加载器组成。
将对象转换为由不同类加载器加载的具有相同名称的类与尝试将String
转换为Integer
没有什么不同,因为尽管具有相同的名称,这些类实际上可能完全不同
答案 1 :(得分:8)
我刚刚花了两天时间来解决这个问题,我终于通过使用java反射解决了这个问题:
// 'source' is from another classloader
final Object source = events[0].getSource();
if (source.getClass().getName().equals("org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptThread")) {
// I cannot cast to 'org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptThread'
// so I invoke the method 'terminate()' manually
Method method = source.getClass().getMethod("terminate", new Class[] {});
method.invoke(source, new Object[] {});
}
希望这有助于某人。
答案 2 :(得分:6)
如果需要强制转换的类实现Serializable,那么:
private <T> T castObj(Object o) throws IOException, ClassNotFoundException {
if (o != null) {
ByteArrayOutputStream baous = new ByteArrayOutputStream();
{
ObjectOutputStream oos = new ObjectOutputStream(baous);
try {
oos.writeObject(o);
} finally {
try {
oos.close();
} catch (Exception e) {
}
}
}
byte[] bb = baous.toByteArray();
if (bb != null && bb.length > 0) {
ByteArrayInputStream bais = new ByteArrayInputStream(bb);
ObjectInputStream ois = new ObjectInputStream(bais);
T res = (T) ois.readObject();
return res;
}
}
return null;
}
用法:
Object o1; // MyObj from different class loader
MyObj o2 = castObj(o1);
答案 3 :(得分:3)
使用接口和java.lang.reflect.Proxy
的东西可能适合您的偏好。使用InvocationHandler
查找并调用目标类的相关方法。 (请注意,如果您执行此操作,您将获得的任何移动代码安全性。)
答案 4 :(得分:2)
无法在不同的classLoader中进行投射。
你有这个解决方法与Gson,示例强制转换对象到YourObject(对象是一个YourObject类,但在其他classLoader中):
function nexttrack()
vlc.playlist.delete(itemId)
vlc.playlist.next()
delete()
end
function delete()
os.remove(filename) -- do nothing at this time
end
我使用此解决方法,因为我在WebApp中编译任何Java代码(在Tomcat上)。此解决方法在生产中运行。
答案 5 :(得分:0)
这是我到达的一篇旧帖子,因为我想做几乎相同的事情,但是它的一个更简单的版本......
如果Foo和加载的类(在我的情况下来自另一个包中的.java类文件)扩展了同一个类,比如AbstractTestClass,它实际上是有效的。
代码:
public AbstractTestClass load(String toLoad) {
try{
Class test = Class.forName("testsFolder.testLoadable");
Constructor ctorlist[] = test.getDeclaredConstructors();
for(Constructor aConstructor : ctorlist){
if(...){// find the good constructor
Object loadedTest = aConstructor.newInstance(new Object[]{/*params*/});
return (AbstractTestClass) test;
}
}
}catch(...){}
return new defaultTestClass();
}
这样我可以将加载的类插入ArrayList<AbstractTestClass>
。