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,CLassLoader并java.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然后仅在指定的类加载器中并适当地重新处理应用程序.我发现使用线程上下文类加载器作为默认的类加载器很方便.