如果只有一个完全限定的名称,如何获取java类的二进制名称?

Ing*_*ngo 14 java reflection jvm

反射类和方法以及类加载器等需要所谓的"二进制"类名来使用.

问题是,如果一个人只有一个完全限定的名称,即一个人在源代码中使用的名称,那么如何获得二进制名称.

例如:

package frege;
public static class RT {
    ....
    public static class X { .... }
}
Run Code Online (Sandbox Code Playgroud)

该类的完全限定名称将是frege.RT.X.然而,要获得类对象,需要编写:

Class.forName("frege.RT$X")
Run Code Online (Sandbox Code Playgroud)

并不是

Class.forName("frege.RT.X")    // fails with ClassNotFoundException
Run Code Online (Sandbox Code Playgroud)

因为X碰巧是一个内在的阶级frege.RT.

一种可能的,但笨拙的,解决办法是更换.$向后,一个接一个,直到Class.forName()不扔ClassNotFoundException了或者有没有更多的.替换.

有没有更好/众所周知/标准的解决方案?我看着在API文档Class,CLassLoaderjava.lang.reflect但没有发现任何有用.

Sim*_* G. 12

现在听起来你想从规范名称中获取完全限定名称(FQN).由于这与简单名称的工作不同,我将添加第二个答案.

如果会导致规范名称冲突,Sun javac命令将不会编译类.但是,通过单独编译,您仍然可以获得具有相同规范名称的两个不同的类.

一个例子:

文件src1\com\stack\Test.java

package com.stack;

public class Test {
    public static class Example {
        public static class Cow {
            public static class Hoof {
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Class<?> cl1 = Class.forName("com.stack.Test$Example$Cow$Hoof");
        Class<?> cl2 = Class.forName("com.stack.Test.Example.Cow.Hoof");
        System.out.println(cl1.getName());
        System.out.println(cl1.getSimpleName());
        System.out.println(cl1.getCanonicalName());
        System.out.println();
        System.out.println(cl2.getName());
        System.out.println(cl2.getSimpleName());
        System.out.println(cl2.getCanonicalName());
    }
}
Run Code Online (Sandbox Code Playgroud)

文件src2\com\stack\Test\Example\Cow\Hoof.java

package com.stack.Test.Example.Cow;

public class Hoof { }
Run Code Online (Sandbox Code Playgroud)

然后编译并执行:

set CLASSPATH=
mkdir bin1 bin2
javac -d bin1 -sourcepath src1 src1\com\stack\Test.java
javac -d bin2 -sourcepath src2 src2\com\stack\Test\Example\Cow\Hoof.java

set CLASSPATH=bin1;bin2
java com.stack.Test
Run Code Online (Sandbox Code Playgroud)

产生输出:

com.stack.Test$Example$Cow$Hoof
Hoof
com.stack.Test.Example.Cow.Hoof

com.stack.Test.Example.Cow.Hoof
Hoof
com.stack.Test.Example.Cow.Hoof
Run Code Online (Sandbox Code Playgroud)

因此,两个类具有相同的规范名称但具有不同的FQN.即使两个类具有相同的FQN和相同的规范名称,如果它们通过不同的类加载器加载,它们仍然可以是不同的.

要解决您的问题,我会看到您可以采取的几种方法.

首先,您可以指定匹配具有最少嵌套量的类,因此在FQN中匹配最少数量的'$'.更新事实证明,Sun javac与此完全相反,并且匹配具有最多嵌套的类.

其次,您可以测试所有可能的FQN,并在有多个FQN时抛出异常.

第三,接受唯一的唯一映射是使用FQN然后仅在指定的类加载器中并适当地重新处理应用程序.我发现使用线程上下文类加载器作为默认的类加载器很方便.