【问题标题】:how to load classes from a jar file and store it in an arraylist如何从 jar 文件中加载类并将其存储在 arraylist 中
【发布时间】:2016-07-24 00:02:45
【问题描述】:

我正在尝试从exchanges.jar 文件中加载类文件(不实现任何通用接口)并将其存储在arraylist 中 以前,我使用

从目录加载 .class 文件(实现通用接口)
package edu.uh.cs.assign2;

import java.io.File;
import java.util.ArrayList;

import edu.uh.cs.iexchangeservices.IExchange;

public class ExchangeManager {
    private ArrayList<IExchange> exchangeList = new ArrayList<IExchange>();

    public ArrayList<IExchange> findClasses() throws Exception {

        File classDirectoryPath = new File(Thread.currentThread()
                .getContextClassLoader()
                .getResource("exchangeservices".replace('.', '/')).getFile());

        return loadExchangeClasses(classDirectoryPath);
    }

    public ArrayList<IExchange> loadExchangeClasses(File classDirectoryPath)
            throws Exception {

        if (!classDirectoryPath.exists())
            throw new LoadExchangesException("path not found");

        String[] exchangeClasses = classDirectoryPath.list();

        for (String exchangeClass : exchangeClasses) {

            if (exchangeClass.endsWith(".class")) {
                Object object = (IExchange) Class.forName(
                        "exchangeservices"
                                + '.'
                                + exchangeClass.substring(0,
                                        exchangeClass.length() - 6))
                        .newInstance();

                if (object instanceof IExchange)
                    exchangeList.add((IExchange) object);
            }
        }
        return exchangeList;
    }

}

【问题讨论】:

  • 我可能是错的,但这听起来不像是好的编程习惯。你想用这个类数组列表做什么?
  • @user 从 jar 加载类所需要做的就是将 jar 放在类路径中:java -cp .;myjar.jar,是否有理由让您觉得需要在运行时加载类?
  • 这些文件实际上是在 jar 文件中吗?您的代码看起来像是在磁盘上寻找它们...?
  • 休斯顿我们有问题!!!!!!!!!

标签: java jar


【解决方案1】:

我假设您要做的是加载一组位于 JAR 文件或任何其他 URL 中的类,然后返回一个包含这些类对象的列表。

我的建议是:

  • 使用类 java.util.jar.JarFile 读取 jar 中的所有条目。
  • 遍历条目,如果给定条目属于某个类(其名称以“.class”结尾),则加载该类并将其添加到已加载类的列表中。

有点像这样:

JarFile jar = new JarFile(jarFile);
for(JarEntry entry: Collections.list(jar.entries())){
   if(entry.getName().endsWith(".class")){
     String className = entry.getName().replace("/", ".").replace(".class","");
     foundClasses.add(loader.loadClass(className));
    }
}

出于加载目的,您可以使用包含 jar 文件的 java.net.URLClassLoader

有点像这样

File jarFile = new File("./jedis.jar");
URLClassLoader loader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()});

您将在foundClasses 列表中找到所有已加载的类。

另一方面,如果您确切知道要加载的类,那么 URLClassLoader 应该足以解决问题。

File jarFile = new File("./jedis.jar");
URLClassLoader loader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()});
foundClasses.add(loader.loadClass("jedi.academy.ObiWan"));
foundClasses.add(loader.loadClass("jedi.academy.Luke"));
foundClasses.add(loader.loadClass("jedi.academy.Anakin"));

如果您希望这个辅助类加载器独立于系统类加载器,请确保在实例化 URLClassLoader 时将父类加载器设置为 null:

URLClassLoader loader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()}, null);

【讨论】:

  • 感谢您回答我的问题。我想知道我是否可以让这些类实现一个通用接口。因为我必须遍历类列表,并且我想存储实现特定接口的特定类。
  • @user1282182 如果这回答了您的问题,请将其标记为这样。
  • @Edwin Dalorzo Sry foundClasses 的类型是什么?是类还是其他东西?
  • @marzie 我想foundClasses 的类型必须是Collection&lt;Class&lt;?&gt;&gt; 或其子类型之一。
最近更新 更多