Niepoprawna składnia do utworzenia typu ogólnego za pomocą symboli wieloznacznych. Typ List<? extends Number>
oznacza pewien typ, który jest lub rozciąga się na Number
. Aby utworzyć wystąpienie tego typu nie ma sensu, ponieważ z konkretyzacji tworzysz coś konkretnego:
new ArrayList<? extends Number>();//compiler:"Wait, what am I creating exactly?"
typy generyczne z symboli wieloznacznych sens tylko dla zmiennych i parametrów metody, ponieważ pozwala to na większą swobodę w co można je przypisać/przekazać.
//compiler:"Okay, so passing in a List<Integer> or a List<Double> are both fine"
public void eatSomeNumbers(List<? extends Number> numbers) {
for (Number number : numbers) {
System.out.println("om nom " + number + " nom");
}
}
Należy pamiętać o ograniczeniach związanych z używaniem symboli wieloznacznych.
List<? extends Number> numList = ...
numList.add(new Integer(3));//compiler:"Nope, cause that might be a List<Double>"
Jak na pierwszy przykład diament to nowa funkcja w Java 7, który umożliwia kompilator wywnioskować rodzaju nowej instancji rodzajowe, w zależności od typu zmiennej to przypisany. W tym przypadku:
List<? extends Number> x = new ArrayList<>();
Kompilator jest najprawdopodobniej wywodząc new ArrayList<Number>()
tutaj, ale co wywnioskować nie ma znaczenia, tak długo, jak jest to ważne zadanie dla danej zmiennej. To był powód, dla którego wprowadzono operatora diamentu - że określenie ogólnego rodzaju nowego obiektu było zbędne, tak długo jak typ uczyniłby go ważnym przydziałem/argumentem.
To rozumowanie ma sens tylko wtedy, gdy pamiętasz, że generics w Javie są czysto kompilacją funkcji językowych, ze względu na type erasure i nie mają znaczenia w czasie wykonywania. Symbole wieloznaczne istnieją tylko z powodu tego ograniczenia. Natomiast w języku C# informacje ogólne pojawiają się w środowisku wykonawczym, a ogólne symbole wieloznaczne nie istnieją w tym języku.
Która wersja Java? – Bill
Pierwszy przykład działa na Java 7 oczywiście, a nie na Java 6, ponieważ opcjonalne diamenty nie były dozwolone w 6. drugim przykładzie nie udać się w obu –
Pierwszy zdecydowanie nie działałby na 6; bez operatora diamentowego. Co do reszty; możesz sprawdzić ten zasób: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html – Bill