如何获取.class文件的包名?

时间:2014-01-04 18:35:25

标签: java class reflection runtime package

我有一个不寻常的问题,涉及在运行时动态加载java .class文件。我想要做的就是加载.class文件并在其基础上创建一个Class对象。

输入:.class文件的绝对路径。

基于它我想通过ClassLoader加载类,所以我需要一个文件所在的根目录路径和完整的类名,例如com.test.MyClass。基于提到的绝对路径,我只能得到一个类名,但是我无法在这个文件中获得一个名为“hiden”的包名。

这是我的“加载类方法”的代码:

    public static void loadClass(String directory){

        // Get file root directory
        String rootDirectory = new File(directory).getParent();

        // Get rid of file extension
        String className = getFileNameWithoutExtension(directory);

        URL[] urls = null;
        ClassLoader cl = null;

        try {
            // Convert File to a URL and save them
            urls = new URL[]{new File(rootDirectory).toURI().toURL()};

            // Create a new class loader with the directory
            cl = new URLClassLoader(urls);

            // Load in the class
            dynamicClass = cl.loadClass(className);
        } 
        catch (MalformedURLException e) 
        {

    } 
    catch (ClassNotFoundException e) 
    {

    }
    catch (NoClassDefFoundError e)
    {
        // Basing on error message get the class package name
        String classPackage = getClassPackage(e.getMessage());

        try {             

           // Load the class once more!
           dynamicClass = cl.loadClass(classPackage);
        } 
        catch (ClassNotFoundException ex) 
        {

        }
    }
}

第二种方法用于从异常消息中获取包名称:

private static String getClassPackage(String errorMsg){

    // Start and end index of cutting
    int startIndex = errorMsg.lastIndexOf(" ") + 1;
    int endIndex = errorMsg.length() - 1;

    // Let's save a substring
    String classPackage = errorMsg.substring(startIndex, endIndex);

    // Replace char '/' to '.'
    classPackage = classPackage.replace('/', '.');

    return classPackage;
}

方法代码 getFileNameWithoutExtension

private static String getFileNameWithoutExtension(String path){
    int start = path.lastIndexOf(File.separator) + 1;
    int end = path.lastIndexOf(DOT);
    end = start < end ? end : path.length();
    String name = path.substring(start, end);

    return name;
}

静态最终变量是:

private static final String DOT = ".";

这是我的问题:是否有可能从.class文件中获取包名而不使用这种技巧?

3 个答案:

答案 0 :(得分:8)

您可以使用Foo.class.getPackage().getName()方法来确定这一点。

    public Package getPackage()

返回:

  

类的包,如果归档或代码库中没有可用的包信息,则返回null。

使用getName():

    public String getName()

返回:

  

Java™语言规范6.5.3节中定义的此包的完全限定名称,例如,java.lang

答案 1 :(得分:0)

由于您已在className中拥有所需数据,因此请再次使用。您不需要getClassPackage方法。

    catch (NoClassDefFoundError e)
    {
        // Basing on error message get the class package name
        //But we already have the class name in className variable!
        //String classPackage = getClassPackage(e.getMessage());

        try {             

           // Load the class once more!
           dynamicClass = cl.loadClass(className);
        } 
        catch (ClassNotFoundException ex) 
        {

        }
    }

如果你只想获得包名(不确定原因),你可以从类名中获取它:

String packageName = className.substring(0, className.lastIndexOf('.'));
dynamicClass = cl.loadClass(packageName);

答案 2 :(得分:0)

你可以这样做 -

String packName = new Object(){}.getClass().getPackage().getName();        
System.out.println(packName);