Generics are not covariant. Np
List<Integer> l1;
List<Number> l2;
l1 = l2; // incompatible types
l2 = l1; // also incompatible
Jednakże wieloznacznej rodzaju oferuje sposób wyrażania kowariancji:
List<? extends Integer> l1;
List<? extends Number> l2 = l1; //legal
l1
jest wyrażony jako List
z jakiś nieznany typu który jest lub obejmuje Integer
. Podobnie, l2
jest pewnego rodzaju, który jest lub rozciąga się na Number
. Od Integer
rozszerza Number
, kompilator wie, przypisywanie l1
do l2
musi być w porządku.
Ta sytuacja jest inna:
<S extends Number, U extends Integer> void someMethod() {
List<U> l1;
List<S> l2 = l1; //incompatible types
}
S
i U
są parametry typu, co oznacza, że są jakieś konkretne argumenty typu przez rozmówców z someMethod
(lub typu inferrence). Argumenty tego typu mogą być konkretnym typem, takim jak Integer
lub przechwytywaniem wieloznacznym.
Chociaż są one również ograniczone, różni się to od używania ograniczonych symboli wieloznacznych, jak wyżej. Parametry typu są ograniczone w deklaracji - w treści metody rozumie się, że nie zmieniają się.Na przykład, powiedzmy, że zarówno S
i U
zostały rozwiązane do Integer
pod numerem:
this.<Integer, Integer>someMethod();
W tym przypadku możemy sobie wyobrazić ciało metoda wygląda następująco:
List<Integer> l1;
List<Integer> l2 = l1; // okay why not?
Byłoby to legalne, ale my akurat się poszczęściło. Jest wiele sytuacji, w których by tak nie było. Na przykład:
this.<Double, Integer>someMethod();
Teraz reimagine ciało metoda:
List<Integer> l1;
List<Double> l2 = l1; // danger!
dzięki czemu można zobaczyć, że ograniczonym parametr typ to coś znacznie różni się od ograniczonego zamiennika, który umożliwia różne typy rodzajowe covariantly "zamienione":
List<Integer> l1;
List<Double> l2;
List<? extends Number> l3;
l3 = l1;
l3 = l2;
Czy możesz pokazać, jak definiujesz je wcześniej dla swojego drugiego przykładu? – Quetzalcoatl
@SaurabhAgarwal nie o to chodzi? Dlaczego "dowolna podklasa" działa, ale podklasa specyficzna nie? – Alnitak
klasa publiczna WildcardsTest
{/ * kod przedstawiony powyżej w 2 * /} – Razvan