2016-02-23 6 views
6

Если у меня естьПочему reflections.getSubTypesOf (Object.class) не находит перечисления?

Reflections reflections = new Reflections("my.package", classLoader, new SubTypesScanner(false)); 

, то это находит мои перечисления классов

Set<Class<? extends Enum>> enums = reflections.getSubTypesOf(Enum.class); 

но это не

Set<Class<?>> classes = reflections.getSubTypesOf(Object.class); 

Есть ли причина для этого?


Возпроизводимо пример:

package cupawntae; 

import org.reflections.Reflections; 
import org.reflections.scanners.SubTypesScanner; 

public class Reflector { 
    public static void main(String[] args) { 
     Reflections reflections = new Reflections("cupawntae", Reflector.class.getClassLoader(), new SubTypesScanner(false)); 
     System.out.println("Objects: " + reflections.getSubTypesOf(Object.class)); 
     System.out.println("Enums: " + reflections.getSubTypesOf(Enum.class)); 
     System.out.println("Enum's superclass: " + Enum.class.getSuperclass()); 
    } 
} 

Enum Класс:

package cupawntae; 

public enum MyEnum { 
} 

Выход:

Objects: [class cupawntae.Reflector] 
Enums: [class cupawntae.MyEnum] 
Enum's superclass: class java.lang.Object 
+1

выглядит как ошибка. Обратите внимание, что если enum реализует какой-либо интерфейс, он неожиданно обнаруживается. Пока ошибка не будет исправлена, вы можете использовать, например, 'ClassPath.from (ClassLoader.getSystemClassLoader()). GetTopLevelClasses (" cupawntae ")' Google Guava. Не так гладко, но выполняет свою работу. –

+1

Спасибо, но похоже, что это задокументировано - хотя это странно в отношении интерфейса. Как вы это узнали? Вы случайно реализовали интерфейс внутри своего целевого пакета? – CupawnTae

ответ

6

Это на самом деле documented behaviour, хотя это, возможно, не особенно ясно, или Intuitiv е:

иметь в виду, что при использовании конструктора new Reflections("my.package"), только URL с префиксом «my.package» будет сканироваться, и любые переходные классы в других URL-адресов, не будут сканироваться (например, если my.package.SomeClass расширяет other.package.OtherClass , чем позже не будет сканироваться). в этом случае использовать другие конструкторы и указать соответствующие пакеты/URLs

редактировать: later revision этого док говорит:

Убедитесь, что сканировать все транзитивно соответствующие пакеты. , например, если ваш класс C расширяет B расширяет A, а оба B и A находятся в другом пакете, чем C, когда сканируется только пакет C - тогда запрос для подтипов A возвращает ничего (переходный), но запрос для подтипов B возвращается C (прямой). В этом случае обязательно сканируйте все соответствующие пакеты априори.

В этом случае java.lang.Enum считается как переходный классом (например, other.package.OtherClass), и поэтому не входят в сканировании, то есть подклассы Enum не включены.

Аналогично, если мы сделаем Reflections в примере вопроса, расширьте что-то вне целевого пакета, например. не

public class Reflector extends Exception { 

то класс больше не находится в сканировании

Objects: [] 
Enums: [class cupawntae.MyEnum] 
Enum's superclass: class java.lang.Object 
+1

Вау, это ужасно.Поэтому, если у вас будет специализированный класс, расширяющий 'AbstractList' или ваше собственное Exception, как вы показали, тогда' reflections.getAllTypes() 'НЕ найдет его. Какой беспорядок. Даже если это предназначено, оно должно каким-то образом измениться. По крайней мере, он должен переходить через java.lang и java.util автоматически! –

+1

О, боже мой. Даже если вы специально включаете 'java.lang' и' java.util' в качестве пакетов, ни 'reflections.getAllTypes()', ни 'reflections.getSubTypesOf (Object.class)' не предоставит вам специализированный Exception/LIst. Так что просто нет возможности получить все ваши классы в этой библиотеке, не так ли? Какой позор. –

+1

Хорошо, последний комментарий, и я закончу. Вне уже упомянутого Guava 'ClassPath', есть https://github.com/lukehutch/fast-classpath-scanner, который делает это также. Я не пробовал, но выглядит довольно зрелым. –

Смежные вопросы