1

Is there a way to get Class X from Test.class

class Test {

    void test() {
        class X {
        }
    }
}

using reflection?

1
  • 2
    You need to understand how the Java compiler / JVM maps local class names to internal class names, then just call Class.forName(...) with the right internal class name. Commented Feb 20, 2015 at 14:01

3 Answers 3

2

It's similar to how you'd do an inner class using Class.forName

class Test {
    class X {} // "Test$X"
}

Except it's prefaced by a number (much like an anonymous inner class) since there can be multiple local definitions

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"
    }
}

It would be interesting to know if the JLS guarantees the numbering based on the order of the code, but I wouldn't place any bets on it.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use the following idiom, assuming a self-contained example in a Main class:

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(){}
            }
        }
    }
}

Output

[void test.Main$Test$1Foo.bar()]

Comments

1

You can identify these anonymous classes using reflection, by accessing the classes field on the ClassLoader object. This field appears to keep track of all the loaded classes. If you then check for classes where getCanonicalName return null, you will then be able to identify these classes. It is not very pretty, but it gets me class X in this case.

The only caveat is that this doesn't appear to work if class X is not referenced anywhere.

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();

  }
}

Output:

Found anonymous class Main$1X

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.