Jedno dzikie karty pozwalają nam zrobić, to zadeklarować typów, które są niezależne od kierunku określonego parametru typu, na przykład „listy jakiejkolwiek liście” :
List<List<?>> listOfAnyList = ...;
listOfAnyList.add(new ArrayList<String>());
listOfAnyList.add(new ArrayList<Double>());
jest to niemożliwe bez zamiennika : * ponieważ listy elementów mogą mieć różne typy od siebie.
A jeśli staramy się go capture, okaże się, że nie możemy:
static <E> void m(List<List<E>> listOfParticularList) {}
m(listOfAnyList); // <- this won't compile
Inną rzeczą dzikie karty pozwalają nam to zrobić parametrów typu nie jest ustawiony dolny pułap. (Parametr typu może być uznana z extends
związany, ale nie super
związany. **)
class Protector {
private String secretMessage = "abc";
void pass(Consumer<? super String> consumer) {
consumer.accept(secretMessage);
}
}
Załóżmy pass
został uznany zamiast wziąć Consumer<String>
. Załóżmy teraz, że mieliśmy Consumer<Object>
:
class CollectorOfAnything implements Consumer<Object> {
private List<Object> myCollection = new ArrayList<>();
@Override
public void accept(Object anything) {
myCollection.add(anything);
}
}
Problem polega na tym, że nie możemy przekazać ją do metody przyjmującej Consumer<String>
. Zgłoszenie Consumer<? super String>
oznacza, że możemy przekazać każdego konsumenta, który akceptuje numer String
. (Zobacz także Java Generics: What is PECS?.)
W większości przypadków symbole wieloznaczne pozwalają nam składać czyste deklaracje.
Jeśli nie musimy używać typu, nie musimy zadeklarować dla niego parametru typu.
* Technicznie również możliwe z raw type, ale surowe typy są zniechęceni.
** Nie wiem, dlaczego Java nie zezwala na super
dla parametru typu. 4.5.1. Type Arguments of Parameterized Types może wskazywać, że to ma coś wspólnego z ograniczeniem typu wnioskowania:
przeciwieństwie do zwykłych zmiennych typu zadeklarowanych w podpis metody, żaden typ wnioskowanie jest wymagane w przypadku korzystania z wieloznacznych. W związku z tym dopuszczalne jest deklarowanie niższych granic na karcie wieloznacznej [& hellip;].
Nie jestem do końca pewny, ale uważam, że ostatnia wersja bez dzikiej karty może odradzać wiele wersji tej samej metody, specyficznych dla każdego typu "Collection" po wywołaniu metody z różnymi typami kolekcji. Ten z dziką kartą poradzi sobie z nimi wszystkimi. – tiguchi
@NobuGames W Javie będzie to jedna metoda, ponieważ generics są wymazywane w czasie kompilacji. – ILMTitan
[oficjalne dokumenty] (https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html) zapewniają dobrą odpowiedź na to pytanie. – Droidman