Chcę mieć obiekt klasy, ale chcę wymusić dowolną reprezentowaną przez niego klasę, aby rozszerzyć klasę A i wdrożyć interfejs B.
Potrafię:
Class<? extends ClassA>
Lub:
Class<? extends InterfaceB>
ale nie mogę zrobić obu. Czy jest na to sposób?
Chcę mieć obiekt klasy, ale chcę wymusić dowolną reprezentowaną przez niego klasę, aby rozszerzyć klasę A i wdrożyć interfejs B.
Potrafię:
Class<? extends ClassA>
Lub:
Class<? extends InterfaceB>
ale nie mogę zrobić obu. Czy jest na to sposób?
Odpowiedzi:
W rzeczywistości możesz robić, co chcesz. Jeśli chcesz udostępnić wiele interfejsów lub interfejsów plus klasa, musisz mieć wygląd wieloznaczny mniej więcej tak:
<T extends ClassA & InterfaceB>
Zobacz samouczek ogólny na stronie sun.com, w szczególności sekcję Parametry typu ograniczenia na dole strony. Jeśli chcesz, możesz podać więcej niż jeden interfejs, używając & InterfaceNamekażdego z nich.
Może się to arbitralnie skomplikować. Aby to zademonstrować, zobacz deklarację JavaDoc Collections#max, która (zawinięta w dwie linie) to:
public static <T extends Object & Comparable<? super T>> T
max(Collection<? extends T> coll)
dlaczego tak skomplikowane? Jak powiedziano w Java Generics FAQ: Aby zachować zgodność binarną .
Wygląda na to, że nie działa to w przypadku deklaracji zmiennych, ale działa, gdy nakłada się ogólną granicę na klasę. Tak więc, aby zrobić to, co chcesz, możesz skoczyć przez kilka obręczy. Ale możesz to zrobić. Możesz zrobić coś takiego, ustanawiając ogólną granicę dla swojej klasy, a następnie:
class classB { }
interface interfaceC { }
public class MyClass<T extends classB & interfaceC> {
Class<T> variable;
}
aby uzyskać, variableże ma ograniczenie, które chcesz. Więcej informacji i przykładów można znaleźć na stronie 3 Ogólnych w Javie 5.0 . Zauważ, że w <T extends B & C>, nazwa klasy musi być pierwsza, a interfejsy następują. I oczywiście możesz wymienić tylko jedną klasę.
?w tym wyrażeniu, więc czy to naprawdę „symbol wieloznaczny”? Pytam, ponieważ nie mogę uruchomić całej koncepcji „rozszerzania dwóch rzeczy naraz”, gdy parametr type naprawdę jest symbolem wieloznacznym.
Nie możesz tego zrobić z parametrami typu „anonimowymi” (tj. Używającymi symboli wieloznacznych ?), ale możesz to zrobić z parametrami typu „nazwanego”. Po prostu zadeklaruj parametr typu na poziomie metody lub klasy.
import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
T t;
}