2013-06-06 18 views
10

Piszę program, który użyje odbicia Java (tj. Class.forName()) do dynamicznego tworzenia instancji klasy na podstawie danych wprowadzanych przez użytkownika. Jednym z wymagań jest to, że instancja, którą tworzy mój program, musi rozciągnąć się o jedną określoną klasę I, nazywaną SomeClass. Moje pytanie brzmi: do przechowywania tego typu klasy, czy powinienem używać ograniczonego generycznego, Class<? extends SomeClass>, lub po prostu nieograniczonego generycznego, Class? Zauważyłem, że niektóre książki w języku Java mówią, że klasa jest jedną z dobrych praktyk używania nieograniczonego generatora symboli wieloznacznych, ale zastanawiam się, czy ma to zastosowanie do sytuacji w moim programie.Java Generics - klasa lub klasa <? extends SomeClass>

Proszę dać mi znać, jeśli moje pytanie nie jest wystarczająco jasne lub potrzebne są jakieś informacje.

Odpowiedz

16

Powinieneś użyć Class<? extends SomeClass>, ponieważ właśnie do tego służą generics.

W czasie, gdy wywołujesz Class.forName, sprawdź, czy jest to nowa klasa w postaci SomeClass.class.isAssignableFrom. W przeciwnym razie powinieneś rzucić IllegalArgumentException lub ClassCastException.

EDYCJA: Alternatywnie, wywołanie asSubclass(SomeClass.class) zrobi to za Ciebie.

Na przykład:

public SomeClass instantiate(String name) 
    throws ClassNotFoundException, InstantiationException, IllegalAccessException { 

    Class<?> raw = Class.forName(name); 

    //throws ClassCastException if wrong 
    Class<? extends SomeClass> generic = raw.asSubclass(SomeClass.class); 

    // do what you want with `generic` 

    return generic.newInstance(); 
} 
+0

@Vulcan tak, ale to nie to co OP określony. Chce, aby wszyscy rozszerzyli 'SomeClass'. – wchargin

+3

Byłoby czystsze po prostu użyć ['asSubclass'] (http: //docs.oracle.com/javase/7/docs/api/java/lang/Class.html#asSubclass \ (java.lang.Class \)) zamiast sprawdzać 'isAssignableFrom', a następnie samemu wyrzucać wyjątek. –

+1

Ponadto, wciąż nie ma uzasadnienia dla niezaznaczonej obsady - twoja metoda pomocnicza powinna po prostu zwrócić 'SomeClass' i nie być generyczna. –