[英]ClassLoader doesn't seem to be returning object correctly
我有一个实现ToTest接口的MyClass类,我希望通过在Tomcat上运行的Web App中的ClassLoader进行检索。
课程如下:
public class MyClass implements ToTest {
public String doStuff(String input) {
return null;
}
}
接口是
public interface ToTest {
public String doStuff(String input);
}
当我实例化类的正常实例时,它正常工作(即看起来是ToTest的一个实例),但是,当我使用我的类加载器时,该对象不会解析为ToTest的实例。
即
Object myObject = new MyClass();
if (myObject instanceof ToTest) {
System.out.println("This is a ToTest");
}
将打印出消息,而:
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("c:\\tomcatfolder\\wtpwebapps\\MyApp\\WEB-INF\\classes").toURI().toURL()});
Class<?> loadedClass = classLoader.loadClass("MyClass");
Object myOtherObj = loadedClass.newInstance();
if (myOtherObj instanceof ToTest) {
System.out.println("This is a ToTest");
}
返回一个看似MyClass对象的对象,但'if instanceof'返回false。
有任何想法吗?
谢谢
这是因为如果你用不同的类加载器加载相同的类,它被认为是一个不同的类。 甚至可以简化您的问题:
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("c:\\tomcatfolder\\wtpwebapps\\MyApp\\WEB-INF\\classes").toURI().toURL()});
Class<MyClass> loadedClass = classLoader.loadClass("MyClass");
Object myOtherObj = loadedClass.newInstance(); //loaded by URLClassLoader
Object myObject = new MyClass(); // loaded by default classloader
// at this point the two objects don't have the same type
如果我们查看您的实际问题,我们会看到myOtherObj
是从与ToTest
不同的类加载器加载的,您可以将其与之进行比较。 这意味着它的类MyClass
没有实现与用于比较的ToTest
相同的ToTest
。
来自JLS :
“在运行时,具有相同二进制名称的几个引用类型可以由不同的类加载器同时加载。这些类型可能表示也可能不表示相同的类型声明。即使两个这样的类型确实表示相同的类型声明,它们也被认为是不同的“。
和
“两个引用类型是相同的运行时类型,如果[...]它们都是类或两种接口类型,由相同的类加载器定义,并具有相同的二进制名称[...]”
正如bmargulies指出的那样,你可以通过将当前的类加载器设置为自定义类的父类来避免这种情况:
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("c:\\tomcatfolder\\wtpwebapps\\MyApp\\WEB-INF\\classes").toURI().toURL()}, getClass().getClassLoader());
您没有将新的类加载器设置为从旧的类加载器继承。 因此,它不与您现有的类加载器共享任何类。 因此,从类加载器中反射创建的对象永远不会是任何类的实例。
我不明白为什么你会想要这个类加载器,但如果你这样做,你需要设置父类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.