我有一个非常奇怪的问题。
我正在使用URLClassLoader从目录动态导入文件。如果我使用文字字符串,代码工作正常,如果我使用变量到文字字符串,工作正常,但这不是我需要的。
package test;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class Test {
public static void main(String[] args) {
try {
File subfolder = new File("C:\\temp\\");
URL classUrl = subfolder.toURI().toURL();
URL[] classUrls = { classUrl };
URLClassLoader ucl = new URLClassLoader(classUrls);
for (File f : subfolder.listFiles()) {
String name = f.getName()
.substring(0, f.getName().lastIndexOf(".")).trim();
if (name.equals("TestClass"))
System.out.println(name);
try {
MyInterface de = (MyInterface) Class.forName("TestClass", true, ucl)
.newInstance();
de.printSomething();
} catch (ClassNotFoundException e) {
}
ucl.close();
}
} catch (MalformedURLException e) {
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我需要的是能够做到这一点:
MyInterface de = (MyInterface) Class.forName(name, true, ucl).newInstance();
但是即使“name”是一个有效的String并且它等于“TestClass”,它也不起作用。
编辑:我收到错误:
java.lang.ClassNotFoundException: TestClass
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at test.Test.main(Test.java:25)
怎么了?
答案 0 :(得分:4)
您的问题似乎与您正在加载的类具有包的事实有关。当Java加载这些类时,它希望找到与该包相关的目录结构。因此,以下代码有效:
try {
File subfolder = new File("/home/glen/TestClass");
URL classUrl = subfolder.toURI().toURL();
URL[] classUrls = { classUrl };
URLClassLoader ucl = new URLClassLoader(classUrls);
for (File f : subfolder.listFiles()[0].listFiles()) {
System.out.println(f.getName());
String name = f.getName()
.substring(0, f.getName().lastIndexOf(".")).trim();// "TestClass";
if (name.equals("TestClass"))
System.out.println(name);
try {
MyInterface de = (MyInterface) Class.forName("test." + name, true, ucl)
.newInstance();
de.printSomething();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ucl.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
请注意我:
test.TestClass
方法Class.forName
本质上,URLClassLoader需要类似JAR的目录结构,如test/TestClass.class
,同时具有包含目录结构的URL根目录。
我的工作理论是,你不只是将name变量更改为字符串文字,因为当我这样做时,它仍然可以正常工作。仔细检查你没有改变任何其他东西。无论哪种方式,我希望这能指出你正确的方向。
答案 1 :(得分:4)
我想这是因为for循环中的ucl.close()。如果有目录,我添加了一些测试:如果在根包中声明,则以下类可以工作并实现自身,如果eclipse配置为在“bin”目录中生成.class文件:
public class Toto {
public Toto(){
// this writes "Toto" in the console if the class is well instanciated
System.out.println("Toto");
}
public static void main(String[] args) {
try {
File subfolder = new File("bin");
URL classUrl = subfolder.toURI().toURL();
URL[] classUrls = { classUrl };
URLClassLoader ucl = new URLClassLoader(classUrls);
for (File f : subfolder.listFiles()) {
String fileName= f.getName();
int suffix = fileName.lastIndexOf('.');
if(f.isDirectory() || suffix==-1){
continue;
}
String name = fileName.substring(0, suffix);
try {
Class.forName(name, true, ucl).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
ucl.close();
} catch (MalformedURLException e) {
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}