2013-04-03 16 views
11

Dlaczego 1 działa, a 2 nie?Java wildcards vs parametry typu

1:

public List<? extends Integer> l1; 
public List<? extends Number> l2 = l1; 

2:

public List<U> l1; 
public List<S> l2 = l1; 
//where U and S have been previously defined as: **S extends Number,U extends Integer** 
+4

Czy możesz pokazać, jak definiujesz je wcześniej dla swojego drugiego przykładu? – Quetzalcoatl

+0

@SaurabhAgarwal nie o to chodzi? Dlaczego "dowolna podklasa" działa, ale podklasa specyficzna nie? – Alnitak

+0

klasa publiczna WildcardsTest {/ * kod przedstawiony powyżej w 2 * /} – Razvan

Odpowiedz

-2

Ponieważ w 1 mówisz dowolnej klasy Sub Integer i Numeru odpowiednio.

Ale w drugiej części mówisz Generic z U i S i podobnie jak te generics nie wspiera Super może odnosić się do pojęcia obiektu klasy Sub o java OOP's.

+0

Możesz tego nie akceptować, ale to jest prawdziwy powód generycznych .. !! –

-1

Look In 1.1 mówisz o dowolnej klasie, która rozszerza Integer, aw 1.2 dowolnej klasie, która rozszerza Number. Teraz jest taki sposób, że Integer jest podklasą liczby, dlatego nie dał żadnego błędu w pierwszym przypadku. Ale to 2,1 mówisz tylko U i tylko u 2,2 S i robisz

public List<S> l2 = l1 

i L1 jest typu U i S nie generyczne nie obsługuje takiego obiektu odwołującego przez jego własne. Będziesz musiał użyć symboli wieloznacznych, takich jak użyte w pierwszym przypadku.

public List<? extends Number> l2 = l1; 

rozwiąże problemu ..

1

BTW: Nie można rozszerzyć Integer, Integer jest klasą final.

// l1 holds any subclass of Integer and, because Integer implements Number it is also a subclass of Number 
public List<? extends Integer> l1; 
// l1 (see above) implements Number so this is fine. 
public List<? extends Number> l2 = l1; 

// Using Integer here instead of your U because you cannot extend Integer - it is final. 
public List<Integer> l3; 
// Make S extend Number 
static class S extends Number { 
    // Implementing the abstract methods of Number 
} 
// NOT valid because l4 must be a List of S not a list of ANY Number and l3 is a List<Integer> - no connection other than a commmon interface. 
public List<S> l4 = l3; 
+0

Twój język jest nieco mylący - myślę, że w niektórych miejscach miałeś na myśli "podklasę"? –

+0

@PaulBellora - Dziękuję - poprawiono. – OldCurmudgeon

3

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;