2013-08-12 10 views
18

Java typu rodzajowego: Jaka jest różnica międzyJava Typ ogólny: różnica między listą <? rozciąga numer> i List <T rozciąga Number>

(1) List <? extends Number> 
(2) List <T extends Number> 

jak na moje rozumienie

(1) List <? extends Number> jest Readonly Lista "nieznany" danych wpisz z super klasy "Liczba". możemy odczytać tylko ten element, ale nie można dodać:

(2) List <T extends Number> Lista typu danych z super klasą "Liczba". możemy czytać i dodawać elementy do listy

Proszę patrz poniższy przykład kodu

class TestGen{ 

     public static void main(String[] args) { 

     double result = 0.0; 

     List<Integer> intList = new ArrayList<Integer>(); 
     intList.add(10); 
     intList.add(20); 
     intList.add(30); 

     result = TestGen.sumOfList1(intList); 
     System.out.println("Result=" + result); 

     result = TestGen.sumOfList2(intList); 
     System.out.println("Result=" + result); 
    } 

    public static double sumOfList1(List<? extends Number> list) { 
     double s = 0.0; 
     for (Number n : list) 
      s += n.doubleValue(); 
     return s; 
    } 


    public static <T extends Number> double sumOfList2(List<T> list) { 

     double s = 0.0; 

     // -- --------------------------------------------------------- 
     // getting error while trying to add new element 
     // list<T> is not applicable for argument(Integer) : Why ? 
     list.add(new Integer(40));      

     for (Number n : list)    
      s += n.doubleValue(); 

     return s; 
    } 
} 

Gdy próbuję dodać Integer (lub nawet obiekt Number) do sumOfList2 następnie uzyskiwanie błąd . Proszę wyjaśnić, co jest nie tak?

Odpowiedz

18

różnica Basic jest jeśli używasz T extends Number wtedy można odwołać się do typu T
na przykład: list.add((T) new Integer(40));
Gdzie jakby użyć ? extends Number to nie może odnosić się do rodzaju, ale nadal można powiedzieć ((List<Integer>)list).add((int) s);

+0

Dlaczego została odrzucona, jakaś wskazówka? Czy coś jest nie tak? – BVMR

+0

Nie jestem pewien, kto głosował .... to rozwiązanie działa, czy możesz rzucić światło, dlaczego wymagane jest odlewanie. list.add ((T) new Integer (40)); podczas gdy dodajemy obiekt tylko klasy podrzędnej (Integer jest podklasą liczby) –

+0

Zgaduję, że daje ci ostrzeżenie typu "typ bezpieczeństwa", gdy rzucisz go na 'T'. – GGrec

1

W sumOfList2, jest określoną podklasą Number, ale może to być dowolna z nich. Na przykład T może być BigDecimal i nie można dodać Integer do List<BigDecimal>.

Jeśli chcesz, aby móc dodać wszystkich typów numeru do listy, to musi być List<Number>:

public static double sumOfList2(List<Number> list) {...} 
10

w izolacji, nie ma m uch różnica. Jednak dwa wystąpienia List<? extends Number> w jednym kontekście są całkowicie niezależne, podczas gdy dwa wystąpienia List<T extends Number> w jednym kontekście odnoszą się do tego samego interfejsu i tego samego interfejsu.

public void addAll(List<? extends Number> to, List<? extends Number> from) { 
    for (Number n: from) { 
     to.add(n); 
    } 
} 

Taki sposób nie działa, ponieważ n nie mogą być dodawane do to, a także nie ponieważ na członkowskie from i to mogą być całkowicie różne.

public <T> void addAll(List<T extends Number> to, List<T extends Number> from) { 
    for (T n: from) { 
     to.add(n); 
    } 
} 

Ta metoda kompiluje dobrze. Nie jest to konieczne; Collections ma lepszą wersję, ale będzie działał bezbłędnie.

+1

W rzeczywistości 'addAll (lista do, ... 'nawet nie kompiluje. Musi to być' void addAll (lista do, ... ' –

-1

Pierwszy przypadek jest bardzo prosty i znany z T extends Number. Ten T jest obiektem należącym do klasy typu lub jej dzieckiem. To oznacza, że ​​jeśli mamy metodę, która używa T jako typ numeru możemy manipulować naszą metodę odpowiednio tj

<T extends Number> void myMethod (List <T> num){ 
    num.add(1); // 1 is an Integer 
    num.add(2.3) // 2.3 is a Double 
} 

Ale w tym * Dzikie znakiem „?'* Sprawa nie wiemy, jaki rodzaj obiektu będzie odwoływać chociaż jeśli rozciąga się numer, ale może to być dowolny rodzaj obiektu

void myMethod(List <? extends Number> num){ 
    // num.add(1); // not a valid statement, as we dont know if '1' is of the type '?' 
    // num.add(2.3) // not a valid statement, as we dont know if '2.3' is of the type '?' 
} 

więc jedyną wartością, która może być zapisana w taki jest null, ponieważ każdy typ obiektu może być pusty.

void myMethod(List <? extends Number> num){ 
     num.add(null) 
    } 

Takie metody są tylko do odczytu.

+0

Twoja pierwsza próbka nie może być faktycznie skompilowana. – yuxh

Powiązane problemy