Возможно ли "исследовать", какие объекты определены в другом объекте посредством отражения во время выполнения?

Рассмотрим этот код:

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 также использует тот же подход.