有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何在类路径之外加载java类?

我有一个程序,我希望用户能够选择一个。java类文件,然后将该类加载到程序中

我使用JFileChooser允许用户选择一个文件。然后,我尝试将该文件转换为URL,并使用URLClassLoader加载该类(如theseanswers所示)

问题是,当我想使用loadClass()方法时,我不知道类的“完整类名”(例如java.lang.String)。所以,我不知道如何让这个方法起作用。有办法得到这个类名吗?还是有其他方法可以做到这一点

以下是我的代码示例:

// Open the file chooser
JFileChooser fileChooser = new JFileChooser();
fileChooser.showOpenDialog(null);
File obtainedFile = fileChooser.getSelectedFile();

// Create the class loader from the file
URL classPath = obtainedFile.toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[] {classPath});

// Get the class from the loader
Class<?> theClassIWant = loader.loadClass("the file name");    // What do I put here??

共 (1) 个答案

  1. # 1 楼答案

    加载单个类文件通常是完全无用的。说班级档案不是唯一的;它有更多相关的类文件。即使您认为“不,只有一个源文件,不要担心这个”,请注意,一个java文件可以轻松生成多个类文件

    因此,有两种选择:

    不要加载类文件。加载jar文件

    使用通常的机制(META-INF/servicesMETA-INF/MANIFEST.MF)在其中放入某种类名,以便知道要加载什么。然后用提供的jar创建一个新的类加载器,加载清单,找出主类,加载它,然后运行它

    尝试确定加载的类文件的“根”,并将其包含在类路径中

    这相当困难——问题是,要“加载”一个类文件,你需要在加载该类之前告诉加载程序该类的完全限定名是什么。但是你怎么知道完全限定名呢?您可以从文件中推测类名(不一定是真的,但通常是),但包是一个更困难的问题

    您可以自己以二进制流的形式打开类文件,并编写一个基本的类文件格式解析器来获得完全限定的类名。对于经验丰富的java程序员来说,这很容易。对于刚接触java的人来说(如果你认为这是个好主意,我想你是这样的)

    您还可以使用现有的工具来实现这一点,例如bytebuddy或asm

    最后,你可以尝试一下在墙上吃意大利面的方法:继续沿着目录往上走,直到它起作用。你知道,如果出现异常,它是不起作用的

    例如,要加载C:\MyDir\Whatever\com\foo\MyApp.class,您首先尝试使用as root dir C:\MyDir\Whatever\com\foo创建一个新的类加载器(请参阅URLClassLoader的API,它是核心java的一部分),然后请求它加载类MyApp

    如果这样做行得通,那就太好了(但通常尝试加载无包类是不可能的,你不应该这样做,CL API可能不支持它,故意的,没有解决方法)

    如果没有,则尝试C:\MyDir\Whatever\com,并加载类foo.MyApp。如果这不起作用,请尝试C:\MyDir\Whatever并加载类com.foo.MyApp,依此类推

    相当大的优势是,如果MyApp.class旁边有另一个类,而MyApp需要它,那么这将很好地工作

    您需要编写一个while循环(使用Paths.getp.getParent()遍历路径结构),捕捉正确的异常,将路径操作到类名中(使用.replace+),当然,还需要创建一个类加载器(URLClassLoader),用它加载类(调用loadClass),如果您打算运行它,类似于thatClass.getConstructor().newInstance()然后thatClass.getMethod("someMethod", String.class, /* all the other args here */).invoke(theInstanceYouJustMade, "param1", /*all other params */)来实际“运行”它,更多内容可以在java.lang.reflect包中找到