Возможно ли "исследовать", какие объекты определены в другом объекте посредством отражения во время выполнения?
Рассмотрим этот код:
object A {
object AA extends A
object AB extends A
object AC extends A
}; class A
Как можно "видеть" объекты, определенные в объекте A
во время выполнения?
Я думал, что метод внутри object A
с некоторым простым кодом отражения будет достаточным, но кажется, что компилятор выравнивает иерархию объектов во время компиляции и создает следующие файлы классов:
-
A.class
- Класс A
-
A$class
- Сопутствующий объект A
-
A$AA$.class
- Объект AA
-
A$AB$.class
- объект AB
-
A$AC$.class
- Объект AC
После компиляции в объекте-компаньоне A
нет знака о AA
, AB
или AC
, который имел бы мой magicMethod
.
Кажется, что класс ClassLoader
имеет некоторые связанные методы для того, что я планирую делать, но все, кажется, ожидают точного строкового имени класса. Есть ли способ попросить ClassLoader найти все файлы классов, начиная с класса, из которого этот метод вызывается (A$
) в пути этого класса?
Ответы
Ответ 1
Код this.getClass.getDeclaredClasses
должен вернуть запрошенную информацию.
Но после нескольких экспериментов с различными инструментами он подозревает, что здесь что-то не работает.
Я пробовал разные вещи в Scala с классами внутри классов вместо объектов и источников Java, и, судя по поведению, он должен явно возвращать ожидаемые результаты, но в настоящее время он этого не делает.
Либо я принципиально ошибаюсь, либо scalac
может забыть поместить некоторые биты метаданных в файлы классов, которые он создает, что приводит к неправильной информации отражения.
См. этот отчет об ошибках.
Ответ 2
Основная проблема заключается в том, что JVM не имеет понятия о внутренних классах. Они были добавлены в Java 1.1, но спецификация JVM осталась полностью неизменной между 1.0 и внедрением invokedynamic (серьезно!).
Как немного взлома, вы всегда можете разобрать имена классов и разделить на $
UPDATE
Для этого вам, к сожалению, придется сканировать путь к классам.
Одним из наиболее известных приложений этой методики является Apache Commons Discovery: http://commons.apache.org/discovery/ (что вы можете использовать, чтобы сделать вашу жизнь проще)
Spring также использует тот же подход.