2016-02-23 12 views
6

Jeśli mamDlaczego reflections.getSubTypesOf (Object.class) nie znajduje wyliczenia?

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

wówczas znajdzie moje klasy enum

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

ale to nie

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

Czy istnieje powód do tego?


Powtarzalne przykład:

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 klasa:

package cupawntae; 

public enum MyEnum { 
} 

wyjściowa:

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

wygląda błędu. Zauważ, że jeśli enum implementuje dowolny interfejs, nagle zostaje znaleziony. Dopóki błąd nie zostanie naprawiony, możesz użyć np. 'ClassPath.from (ClassLoader.getSystemClassLoader()). GetTopLevelClasses (" cupawntae ")' z Google Guava. Nie tak gładko, ale wykonuje swoją robotę. –

+1

Dzięki, ale wygląda na to, że jest udokumentowany - choć to dziwne, jeśli chodzi o interfejs. Jak to odkryłeś? Czy przypadkiem zaimplementowałeś interfejs wewnątrz swojej docelowej paczki? – CupawnTae

Odpowiedz

6

To jest rzeczywiście documented behaviour, choć to zapewne nie jest szczególnie wyraźny lub Intuitiv e:

mieć świadomość, że podczas korzystania z konstruktora new Reflections("my.package"), adresy URL tylko z przedrostkiem „my.package” zostanie zeskanowany, a wszelkie przechodnie zajęcia z innych adresów URL nie będą skanowane (na przykład, jeśli my.package.SomeClass rozciąga other.package.OtherClass , niż później nie będzie skanowany). w takim przypadku korzystać z innych konstruktorów i określenie odpowiednich pakietów/URL

edit: later revision tego dokumentu mówi:

Upewnij się, aby skanować wszystkie przechodni odpowiednich pakietów. na przykład, biorąc pod uwagę, że klasa C rozszerza B rozszerza A, a zarówno B jak i A znajdują się w innym pakiecie niż C, gdy skanowana jest tylko paczka C - wtedy zapytanie o podtypy A nie zwraca nic (przechodnia), ale zapytanie dla podtypów B zwraca C (bezpośredni). W takim przypadku należy przeskanować wszystkie odpowiednie pakiety a priori.

W tym przypadku java.lang.Enum liczy się jako czasownik klasy (jak other.package.OtherClass), a zatem nie jest wliczone w skanowaniu, czyli podklasy Enum nie zostały uwzględnione.

Podobnie, jeśli podamy Reflections w przykładzie pytania, wyciągniemy coś poza pakiet docelowy, np.

public class Reflector extends Exception { 

następnie klasa nie jest już znaleźć w skanie

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

Wow, to okropne.Więc jeśli masz wyspecjalizowaną klasę rozszerzającą 'AbstractList' lub swój własny wyjątek, jak pokazałeś, to' reflections.getAllTypes() 'NIE znajdzie tego. Co za bałagan. Nawet jeśli jest to zamierzone, powinno to zostać jakoś zmienione. Przynajmniej powinien przejść automatycznie java.lang i java.util! –

+1

O mój boże. Nawet jeśli specjalnie dodajesz 'java.lang' i' java.util' jako pakiety, ani 'reflectionions.getAllTypes()' ani 'reflections.getSubTypesOf (Object.class)' dostarczy Ci wyspecjalizowanego wyjątku/LIst. Więc nie ma sposobu, aby uzyskać wszystkie zajęcia z tą biblioteką, prawda? Jaka szkoda. –

+1

Dobra, ostatni komentarz, a ja skończę. Poza wspomnianą już klasą "ClassPath" Guawy, istnieje również https://github.com/lukehutch/fast-classpath-scanner, która również to robi. Nie próbowałem tego, ale wygląda całkiem dojrzale. –

Powiązane problemy