В настоящее время я реализую метод, который имеет один параметр класса Class, и этот метод возвращает логическое значение, если данный объект класса требует, чтобы экземпляр этого объекта включал класс для его экземпляра.
Этот метод работает в настоящее время следующим образом:
if (clazz.getEnclosingClass() == null) {
return false;
}
if (clazz.isAnonymousClass() || clazz.isMemberClass()) {
return !Modifier.isStatic(clazz.getModifiers());
}
if (clazz.getEnclosingConstructor() != null) {
return true;
}
final Method enclosingMethod = clazz.getEnclosingMethod();
if (enclosingMethod != null) {
return !Modifier.isStatic(enclosingMethod.getModifiers());
}
Чтобы объяснить, почему он сконструирован как таковой:
- Сначала он проверяет, является ли он классом верхнего уровня, если это так, алгоритм может безопасно вернуть false
- Если класс является анонимным или классом-членом, для него требуется закрывающий экземпляр, если он не статичен (класс anynmous является автоматически статическим, если он объявлен в статическом конструкторе/методе/блоке-инициализаторе)
- Теперь класс можно считать локальным классом (без учета массивов и примитивов), поэтому он определяется как конструктором, так и методом инициализатора. Однако, в отличие от анонимного класса, локальный класс никогда не считается статическим, но для него требуется закрытый экземпляр, если локальный класс определен в нестационарном блоке.
- Конструктор никогда не статичен, поэтому в этом случае return true
- Если он определен в методе, верните true, если метод не является статическим
Мне нужен шаг 6, чтобы определить, находится ли локальный класс в блоке статического инициализатора или в блоке инициализатора экземпляра, поэтому я выполнил реализацию для этой функции.
Итак, здесь, где API отражений немного короче. Там нет метода Class.getEnclosingInitializer()
или такого, и нет класса, который представляет инициализатор в пакете отражения.
Не является ли инициализатор блоком членом класса? В спецификации java 1.8 интерфейс Member имеет только классы реализации Field, Executable (с подклассами Constructor и Method), а затем есть MemberName, которое выходит за рамки для большинства пользователей отражения.
Я не уверен, что люди, стоящие за спецификацией, забыли об этой ситуации, а локальные классы на самом деле должны быть статическими, если они объявлены в статическом методе/инициализаторе (например, анонимные классы). Но мне кажется, что с этой точки зрения ему не хватает этой последней последовательности.
И есть ли у кого-нибудь идея о том, как определить, в каком типе блока инициализатора объявлен локальный класс?
Я не очень люблю копать поля для синтетического типа, равного ему, охватывающего класс, или прокручивать его конструкторы для чего-то вроде этого (sidenote: объекты Parameter из Constructor.getParameters()
всегда возвращают false на isImplicit()
и isSynthetic()
независимо от того, что я пытаюсь... это просто кажется неправильным). Поэтому, если я могу избежать таких решений, которые были бы замечательными.