Как найти всех наследников java

Казалось бы ответ очевиден:

(new Reflections("package")).getSubTypesOf(SuperClass.class)

Однако эта конструкция находит не всех наследников, в случае, если иерархия разнесена на несколько пакетов.

Есть следующие классы:

package1.ParentClass extemds SuperClass
package2.ChildClass extends ParentClass

Пакеты package1 и package2 не вложенные.

Конструкция

(new Reflections("package1")).getSubTypesOf(SuperClass.class)

Ожидаемо вернёт package1.ParentClass

А вот конструкция

(new Reflections("package2")).getSubTypesOf(SuperClass.class)

Наш package2.ChildClass не вернёт, хотя это очевидный наследник SuperClass.

Я понимаю. что могу в ручную пробежаться по всем классам пакета и собрать нужные. Но неужели нет стандартного способа?

И ещё, объясните, почему по умолчанию ChildClass не находится? Для меня это было очень неожиданное поведение от org.reflections.Reflections.

UPD:
Изучил исходники ядра org.reflections, всё стало на свои места.
Если кратко, java именно так и реализует Reflections.
У каждого класса в рефлексии есть только ссылка на родителя. Поэтому поиск подклассов в любом случае перебор.
Почему в этом переборе нет супер классов из иных пакетов — вопрос отдельный. Так реализовано.

Для каждой конкретной задачи нужно использовать оптимальное решение. Но хотелось бы услышать о уже существующих решениях, которые позволяют найти всех потомков, кроме java org.reflections.

UPD: Ещё один интересный и нетрудоёмкий способ.

Reflections reflections = new Reflections("package1", new SubTypesScanner())
Set<Class<?>> subTypes = new HashSet<>();
for (String className : reflections.getStore().get(SubTypesScanner.class.getSimpleName()).values()) {
    try {
        Class subType = Class.forName(className);
        if (SuperClass.class.isAssignableFrom(subType)) {
            subTypes.add(subType);
        }
    } catch (ClassNotFoundException e) {
        throw new RuntimeException("Этого не может быть:)", e);
    }
}
return subTypes;

Данное решение перебирает все классы пакета (кроме наследников object)

reflections.getStore().get(SubTypesScanner.class.getSimpleName()).values()

и проверяет на то, что они являются наследником или реализуют SuperClass

SuperClass.class.isAssignableFrom(subType)

По производительности, по крайней мере, лучше, чем поиск по всем пакетам и последующая фильтрация

Казалось бы ответ очевиден:
(new Reflections(«package»)).getSubTypesOf(SuperClass.class)

Однако эта конструкция находит не всех наследников, в случае, если иерархия разнесена на несколько пакетов.
Есть следующие классы:
package1.ParentClass extemds SuperClass
package2.ChildClass extends ParentClass

Пакеты package1 и package2 не вложенные.
Конструкция
(new Reflections(«package1»)).getSubTypesOf(SuperClass.class)

Ожидаемо вернёт package1.ParentClass
А вот конструкция
(new Reflections(«package2»)).getSubTypesOf(SuperClass.class)

Наш package2.ChildClass не вернёт, хотя это очевидный наследник SuperClass
Я понимаю. что могу в ручную пробежаться по всем классам пакета и собрать нужные. Но неужели нет стандартного способа?
И ещё, объясните, почему по умолчанию ChildClass не находится? Для меня это было очень неожиданное поведение от org.reflections.Reflections
UPD:
Изучил исходники ядра org.reflections, всё стало на свои места.
Если кратко, java именно так и реализует Reflections.
У каждого класса в рефлексии есть только ссылка на родителя. Поэтому поиск подклассов в любом случае перебор.
Почему в этом переборе нет супер классов из иных пакетов — вопрос отдельный. Так реализовано.
Для каждой конкретной задачи нужно использовать оптимальное решение. Но хотелось бы услышать о уже существующих решениях, которые позволяют найти всех потомков, кроме java org.reflections.
UPD: Ещё один интересный и нетрудоёмкий способ.
Reflections reflections = new Reflections(«package1», new SubTypesScanner())
Set> subTypes = new HashSet<>();
for (String className : reflections.getStore().get(SubTypesScanner.class.getSimpleName()).values()) {
try {
Class subType = Class.forName(className);
if (SuperClass.class.isAssignableFrom(subType)) {
subTypes.add(subType);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(«Этого не может быть:)», e);
}
}
return subTypes;

Данное решение перебирает все классы пакета (кроме наследников object)
reflections.getStore().get(SubTypesScanner.class.getSimpleName()).values()

и проверяет на то, что они являются наследником или реализуют SuperClass
SuperClass.class.isAssignableFrom(subType)

По производительности, по крайней мере, лучше, чем поиск по всем пакетам и последующая фильтрация

Ответ

И ещё, объясните, почему по умолчанию ChildClass не находится?

Причина в том, что класс ChildClass является не прямым наследником SuperClass, а через класс ParentClass.
Reflections не уходит рекурсивно на проверку «родителей-родителей» и так далее, поэтому для обнаружения факта наследования через «промежуточные» классы необходимо загрузить пакеты со всеми «промежуточными» классами. В данном случае для того чтобы определить факт наследования ChildClass от SuperClass необходимо так же загрузить ParentClass. Лишние классы из полученного множества(Set) можно отфильтровать по имени пакета.
(new Reflections(«package1″,»package2»))
.getSubTypesOf(SuperClass.class)
.stream()
.filter(c->c.getPackage().getName().equals(«package2»)).collect(Collectors.toSet());

1) Если неизвестен пакет «package1» то можно загрузить реализации из всех пакетов и потом отфильтровать по нужному пакету «package2»:
Set

> s = new Reflections(
ClasspathHelper.forClass(SuperClass.class))
.getSubTypesOf(SuperClass.class)
.stream()
.filter(c->c.getPackage().getName().equals(«package2»))
.collect(Collectors.toSet());

или
Set> s = new Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forClass(SuperClass.class))
.filterInputsBy(new FilterBuilder().excludePackage(«package2»)))
.getSubTypesOf(SuperClass.class);

2) В качестве более производительной альтернативы можно воспользоваться стандартными средствами “java core” и получить все файлы-классы пакета и их уже рекурсивно проверить на наличие искомого наследника.
public static Set> loadClasses(String packageName)
throws ClassNotFoundException {
Set> classes = new HashSet<>();
URL resource = Thread.currentThread()
.getContextClassLoader()
.getResource(packageName.replace(‘.’, ‘/’));
File directory
= new File(resource.getFile());
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
if (files == null || files.length == 0) {
return classes;
}
for (File file : files) {
//в другие пакеты уходить ненужно
if (file.isFile() && file.getName().endsWith(«.class»)) {
classes.add(Class
.forName(String.format(«%s.%s»,
packageName,
file.getName().substring(0, file.getName().indexOf(«.»)))));
}
}
return classes;
}

public static boolean checkAllParents(Class

type, Class hasParentType) {
Class parent = type.getSuperclass();
if (parent == Object.class) {
return false;
}
if (parent.getClass() == hasParentType.getClass()) {
return true;
}
return checkAllParents(parent, hasParentType);
}

Set

> s = loadClasses(«package2»).stream()
.filter(i->checkAllParents(i, SuperClass.class))
.collect(Collectors.toSet());

Asked
11 years, 1 month ago

Viewed
16k times

I would use http://code.google.com/p/reflections/

Using Reflections you can query your metadata such as:

  • get all subtypes of some type
  • get all types/methods/fields annotated with some annotation, w/o annotation parameters matching
  • get all resources matching matching a regular expression

This can be used in an indexed or cached mode. As @Jagger suggests, a brute force search of every class is relatively slow. You can also limit the search by package e.g. com.mycom.*

answered Apr 23, 2012 at 8:05

Peter Lawrey's user avatar

Peter LawreyPeter Lawrey

524k77 gold badges749 silver badges1128 bronze badges

3

0 / 0 / 0

Регистрация: 12.04.2011

Сообщений: 5

1

работа с классами — получение наследников

12.04.2011, 17:40. Показов 2013. Ответов 3


Студворк — интернет-сервис помощи студентам

имеем набор скомпилированных Java классов. Эти классы представляют собой иерархию. Все классы находятся в одном java package. Необходимо динамически загружать и анализировать иерархию классов. При указании имени класса необходимо получить имена всех классов данного пакета, которые являются наследниками заданного класса/интерфейса. Предложите идеи… заранее благодрарен



0



unknown

12.04.2011, 17:44

2

механизм RTTI

0 / 0 / 0

Регистрация: 12.04.2011

Сообщений: 5

12.04.2011, 17:52

 [ТС]

3

а возможно поподробнее, я новичок в работе с Java :-<



0



unknown

12.04.2011, 18:50

4

http://dmitry.ints.net/library/prog/link/Java/Java/Chapter12.html

можно прослеживать иерархию от текущего класса к его предкам, но не наоборот. для этого нужно организовать через ссылки на

IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

12.04.2011, 18:50

Помогаю со студенческими работами здесь

Работа с классами
Ввести прямоугольную матрицу. Элементами матрицы являются символы. Пользователь может переставлять …

Работа с классами
Здравствуйте, такой вопрос, как указать в функции тип аргументов и как потом эти значения этих…

Работа с классами
Доброго времени суток! Вопрос такого плана… дано задание сделать программу управления делами и…

Работа с классами
Помогите плз

Определите значение переменных а, х, с после выполнения следующих команд:
class…

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

4

Если у меня есть какой-то абстрактный (или нет, не важно) класс — могу ли я найти все классы, которые наследуются от этого класса?

2 ответа

Лучший ответ

Как указал в комментарии, это называется иерархией типов. Чтобы найти это в IntelliJ, либо используйте ярлык ^ + H , либо перейдите в раздел «Навигация и тип иерархии».

Screenshot


2

Community
23 Май 2017 в 12:12

Это может зависеть от привязки вашего ключа, но из того, что я помню по умолчанию в Idea, это ctrl + H (или эквивалент ctrl на вашей платформе).

Если это не так, то вам следует знать ярлык : ctrl + shift + A , который позволяет вам найти действия (и перечисляет их с привязкой клавиш) на основе случайного запроса!


1

Mateusz Dymczyk
4 Фев 2015 в 01:28

Понравилась статья? Поделить с друзьями:
  • Как найти индекс динамики в статистике
  • Как найти диагональ в квадрате зная сторону
  • Как найти гражданина сша
  • Как найти знак электрического заряда
  • Как найти клиента для наружной рекламы