Java中的动态类加载(枚举)

时间:2009-08-13 22:59:36

标签: java reflection oop

我有一个问题,我希望使用反射在运行时生成一组类中的一个的实例。但是,我遇到了麻烦。我想让所有涉及的类都注册自己,这样就可以从GUI中选择合适的类。我可以在每个文件中使用静态代码块来提供整洁的OO解决方案。但是,java类加载器在需要时专门加载类,因此如果尚未使用所需的类,则不会注册它。

没有直接提供静态名称列表,或者运行底层的类/ java文件(无论如何打包到jar中时会破坏),有没有办法强制加载某些包的类?

基本上,我希望能够从指定的超类中添加新类,而无需更改/添加任何其他代码。

7 个答案:

答案 0 :(得分:3)

澄清一下,你的问题不是关于“Java中的动态类加载”,而是关于动态类枚举 - 你知道如何加载类,你只是不知道你是什么类想。

Google快速推出了此页面:http://forums.sun.com/thread.jspa?threadID=341935&start=0&tstart=0

从该页面开始,这里有一些应该有效的示例代码:

public static Class[] getClasses(String pckgname)
        throws ClassNotFoundException {
    ArrayList<Class> classes = new ArrayList<Class>();
    // Get a File object for the package
    File directory = null;
    try {
        ClassLoader cld = Thread.currentThread().getContextClassLoader();
        if (cld == null) {
            throw new ClassNotFoundException("Can't get class loader.");
        }
        String path = '/' + pckgname.replace('.', '/');
        URL resource = cld.getResource(path);
        if (resource == null) {
            throw new ClassNotFoundException("No resource for " + path);
        }
        directory = new File(resource.getFile());
    } catch (NullPointerException x) {
        throw new ClassNotFoundException(pckgname + " (" + directory
                + ") does not appear to be a valid package");
    }
    if (directory.exists()) {
        // Get the list of the files contained in the package
        String[] files = directory.list();
        for (int i = 0; i < files.length; i++) {
            // we are only interested in .class files
            if (files[i].endsWith(".class")) {
                // removes the .class extension
                classes.add(Class.forName(pckgname + '.'
                        + files[i].substring(0, files[i].length() - 6)));
            }
        }
    } else {
        throw new ClassNotFoundException(pckgname
                + " does not appear to be a valid package");
    }
    Class[] classesA = new Class[classes.size()];
    classes.toArray(classesA);
    return classesA;
}

答案 1 :(得分:2)

Spring Framework根据注释进行组件扫描。

例如,查看ClassPathScanningCandidateComponentProvider课程。你可以根据接口/基类做同样的事情,它应该适用于所有 LOCAL 类。对于java中的 ALL 类,无法执行此操作。

答案 2 :(得分:1)

Class.forName(“class name here”);

你将拥有一个带有类名的String变量。 假设您有一个字符串列表,其中包含您要加载的所有类名(并使用静态代码块自动注册:

for(String className:classesToBeLoaded)     的Class.forName(类名);

答案 3 :(得分:1)

通过这个例子:

public class MainClass {

  public static void main(String[] args){

    ClassLoader classLoader = MainClass.class.getClassLoader();

    try {
        Class aClass = classLoader.loadClass("com.jenkov.MyClass");
        System.out.println("aClass.getName() = " + aClass.getName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

}

答案 4 :(得分:1)

如果你的课程在文件系统中的jar中有可能(这可能听起来很荒谬,但我看过从ldaps加载的类)

因此,如果您的类位于jar中的文件系统中,您可以执行以下操作:

下面的伪java:

  String classPath = System.getClassPath(); 
  String [] classPathParts = classpath.split(";"); // or :

  String [] allTheClasses = []

  for each ( file  in classPathParts ) {
      if( file is directory ) {
           allTheClasses.addAll( file.contents );
      } else if ( file is ".jar" ) {
           allTheClasses.addAll( getZippedNamesFrom( file ) );

      }
 }

 // At this point you would have all the classes in the array ( list ) .

 String [] packageNames = {"a.b.c", "d.e.f" };
 for each ( String  clazzName in allTheClasses ) {
       if ( packageNames.contains( clazzName.getPackageName() ) ) {
           Class.forName( clazzName ); // load it and have the static block run
           // Or run it your self
       }
 }

 // End of the story.

很久以前我就是这样做的。

我使用这种方法在不到一秒的时间内加载大约70k +类名。在我的情况下,我动态地寻找大约10个类,所以整个过程花了我大约1.1秒。

答案 5 :(得分:1)

答案 6 :(得分:0)

我建议将所有“动态”类放入一个包中。扫描该目录以获取每个文件名,然后在Class.forName()中使用它来加载和注册每个类。

我昨天刚问了一个类似的问题,得到了一些很好的反馈。

Create new class from a Variable in Java