Tak naprawdę zawężanie poprzez ’?’ mówi o tym, że typ jest kompletnie nieznany – więc w rzeczy samej nie powoduje żadnego zawężenia.
List versus List<?> versus List<Object>
Powstaje więc pytanie – skoro znak ’?’ nie powoduje, żadnego zawężenia to po co go używać? Może lepiej będzie nie używać w ogóle typów ogólnych (List list = …) lub też opierać się o typ Object (List<Object> list = …) jako nadrzędny dla innych typów?
? nie pozwala na dodawanie obiektów
Jedną z konsekwencji korzystania z zawężenia typu ’?’, jest to, że do takiego typu nie można dodawać elementów innych niż null:
List<?> list = new ArrayList<>();
list.add(""); //nie zadziala
list.add(new Object()); //nie zadziala
list.add(null); //ale to juz zadziala
? pozwala na korzystanie z elementów, ale tylko jak z typu Object
Elementy w kolekcji zawężonej znakiem ’?’ będą traktowane jakby były typu Object – można posługiwać się takimi metodami jak toString czy equals:
static void print(List<?> collection){
collection.forEach(e -> System.out.println(e.toString()));
}? pozwala na przypisanie bardziej zawężonych typów
Z racji tego że, zawężenie ’?’ jest „bardzo ogólnym”, stąd możliwe jest przypisanie „bardziej zawężonych” typów:
List<?> list;
List<String> listOfStrings = new ArrayList<>();
List<? extends Number> listOfNumbers = new ArrayList<>();
list = listOfStrings; // nie ma problemu
list = listOfNumbers; // tutaj tez nie ma problemuA jakie to ma konsekwencje dla zwykłych klas?
Działa to podobnie jak dla klasy List. Spójrzmy na przykład bardzo prostej uogólnionej klasy:
class Getter<T> {
public T get(T t){
return t;
}
}Próbując użyć tej klasy z zawężeniem typu ’?’ mamy następującą sytuację:
Test<?> test = new Test<>();
String s = test.get(""); // nie zadziala
Object o = test.get(null); // zadziala, ale czy ma to sens?Jak widać, metoda działa tylko dla wartości null. A typ zwracany to Object.
Warto zajrzeć
1. https://docs.oracle.com/javase/tutorial/java/generics/unboundedWildcards.html
