当我只有一个没有包的名称时,如何找到一个Java类?

时间:2019-01-08 09:18:53

标签: java class classpath

当我只有名称但没有包时如何在Java中定位(实例化)一个类?代码

Class<?> clazz = Class.forName( "className" );

抛出 ClassNotFoundException ,尽管类路径上没有“ className”。它仅与完整的软件包名称一起使用。代码

URL url = SomeClass.getClass().getClassLoader().findResource( "className.class" );

返回null。

这不是重复的,因为使用软件包列表的解决方案无法回答“无软件包”问题。相反,它们依赖于预定义或外部配置的软件包列表。因此,“仅通过简单名称来反射地查找类”不是重复的,而是提供了一种对程序包进行入侵的解决方案。

有没有可用的Java方法来实现这一目标?

我自己的答案是:

不。 Class,ClassLoader或任何其他Java类都不提供此功能。我写了一小堂课来解决这个问题。 System.out.println 的最后一行给出了类的位置。请随时使用并使其适应您的要求。

package com.lemcke.util;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassLocator {

/**
 * Locates a class by its name. Searches the whole {@code classpath}.
 * 
 * @param name
 *            Name of the class (without package)
 * @return full package name of the class or {@code null} if not found
 */
public String locateClass( String name ) throws IOException {
    if ( name == null || name.length() == 0 ) {
        return null;
    }
    if ( name.endsWith( ".class" ) == false ) {
        name += ".class";
    }
    String found = null;
    String cp = System.getProperty( "java.class.path" );
    String[] paths = cp.split( "[,;]" );

    for ( String pathname : paths ) {
        System.out.println( pathname );
        if ( pathname.endsWith( ".jar" ) ) {
            found = locateClassInJar( name, pathname );
            if ( found != null ) {
                break;
            }
        } else {
            found = locateClassInFolder( name, new File( pathname ) );
            if ( found != null ) {
                found = found.substring( pathname.length() + 1 );
                break;
            }
        }
    }
    if ( found != null ) {
        found = found.substring( 0, found.length() - ".class".length() )
                .replace( '/', '.' ).replace( '\\', '.' );
    }
    return found;
}

private String locateClassInFolder( String name, File path )
        throws IOException {
    File f = new File( path + "/" + name );
    if ( f.exists() ) {
        return f.getPath();
    }
    String found = null;
    for ( File entry : path.listFiles() ) {
        if ( entry.isDirectory() ) {
            System.out.println( entry );
            found = locateClassInFolder( name, entry );
            if ( found != null ) {
                break;
            }
        }
    }
    return found;
}

private String locateClassInJar( String name, String jarpath )
        throws IOException {
    name = "/" + name;
    JarFile jarFile = new JarFile( jarpath );
    Enumeration<JarEntry> entries = jarFile.entries();
    String found = null, entry = null;
    while ( entries.hasMoreElements() ) {
        entry = entries.nextElement().getName();
        if ( entry.endsWith( name ) ) {
            found = entry;
            break;
        }
    }
    jarFile.close();
    return found;
}

/**
 * @param args
 * @throws IOException
 */
public static void main( String[] args ) throws IOException {
    ClassLocator locator = new ClassLocator();
    String found = locator.locateClass( args[0] );
    System.out.println( "found = " + found );
}

}

1 个答案:

答案 0 :(得分:0)

通常情况下,无法通过部分名称加载类。

实际上,这是可能的,但并不容易。您可以查看spring源代码以检查它们如何实现此目标。