我们可以使用反射获得本地课程吗?

时间:2015-02-20 13:58:05

标签: java

有没有办法从Test.class获取Class X

class Test {

    void test() {
        class X {
        }
    }
}

使用反射?

3 个答案:

答案 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