Typy uogólnione – zawężenie poprzez ’?’ (unbounded wildcard)

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 problemu

A 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

Pozostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *