有没有办法从Test.class获取Class X
class Test {
void test() {
class X {
}
}
}
使用反射?
答案 0 :(得分:2)
它类似于您使用Class.forName
class Test {
class X {} // "Test$X"
}
除非它以数字开头(非常类似于匿名内部类),因为可以存在多个本地定义
class Test {
void test() {
class X { // "Test$1X"
}
}
void test2() {
class X { // "Test$2X"
}
class Y { // "Test$1Y"
}
System.out.println(new X(){}) // "Test$1"
System.out.println(new X(){}) // "Test$2"
System.out.println(new Y(){}) // "Test$3"
}
}
知道JLS是否根据代码的顺序保证编号会很有趣,但我不会在其上下任何赌注。
答案 1 :(得分:1)
假设Main
类中有一个自包含的示例,您可以使用以下习语:
public class Main {
public static void main(String[] args) throws Exception {
Class c = Class.forName("test.Main$Test$1Foo");
// testing methods
System.out.println(Arrays.toString(c.getDeclaredMethods()));
}
static class Test {
void test() {
class Foo {
void bar(){}
}
}
}
}
<强>输出强>
[void test.Main$Test$1Foo.bar()]
答案 2 :(得分:1)
您可以通过访问classes
对象上的ClassLoader
字段,使用反射来识别这些匿名类。此字段似乎跟踪所有已加载的类。如果您然后检查getCanonicalName
返回null的类,那么您将能够识别这些类。它不是很漂亮,但在这种情况下它会让我上课X
。
唯一需要注意的是,如果没有在任何地方引用类X
,这似乎不起作用。
public class Main {
public static void main(String... args) throws NoSuchFieldException, IllegalAccessException {
class X {
}
ClassLoader classLoader = RiskWrapper.class.getClassLoader();
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(Permission perm) {
}
});
Field classes = ClassLoader.class.getDeclaredField("classes");
classes.setAccessible(true);
Vector<Class<?>> loadedClasses = (Vector<Class<?>>)classes.get(classLoader);
Class<X> xClass = X.class;
for(Class<?> loadedClass : loadedClasses) {
if(loadedClass.equals(xClass)) {
System.out.println("Found anonymous class " + loadedClass.getName());
}
}
System.out.println();
}
}
输出:
发现匿名类Main $ 1X