2015-11-16 9 views
5

Sto cercando di capire i diversi risultati di compilazione di codice apparentemente analogo. Sembra che sia possibile trasmettere un List<Object> a List<T> ma solo se T non è limitato da una classe concreta. Quindi, dato ...Cast elenco di oggetti da elencare di classe 'parametro di tipo

List<Object> bis = new ArrayList<>(); 

I seguenti compila in class Test<T> così come in class Test<T extends CharSequence> ma non in class Test<T extends BigDecimal>class Test<T extends BigDecimal & CharSequence>.

List<T> result = (List<T>) bis; 

Così dove la differenza proviene da per T delimitata con un tipo di classe e di un tipo di interfaccia?

Edit:

Alcuni codice completo per ogni richiesta. Si compila con un avviso del compilatore nella riga 9. Non è infatti sicuro operare su articoli di result come se fossero istanze di CharSequence risultati in un ClassCastException.

public class Sandbox<T extends CharSequence> { 

    public static void main(String[] args) { 
     new Sandbox<CharSequence>().foo(); 
    } 

    private void foo() {  
     List<Object> bis = Arrays.asList(Integer.valueOf(1)); 
     List<T> result = (List<T>) bis; 
     System.out.println(result); 
    } 
} 

Tuttavia, questo non può essere compilato a tutti:

public class Sandbox<T extends BigDecimal> { 

    public static void main(String[] args) { 
     new Sandbox<BigDecimal>().foo(); 
    } 

    private void foo() {  
     List<Object> bis = Arrays.asList(Integer.valueOf(1)); 
     List<T> result = (List<T>) bis; 
     System.out.println(result); 
    } 

} 

errore del compilatore in linea 9: non può lanciare List<Object> a List<T>.

+1

Richiede più codice. Puoi dare la (e) linea (e) esatta (i) che sta fallendo per te? – markspace

+1

Non è sicuro digitare cast 'List ' su 'List ' dove 'T' può assumere un valore diverso da' Object'. Tipo di interfaccia * vs *. il tipo di classe non ha importanza. Se un dato compilatore Java diagnostichi il problema è una domanda diversa. –

+1

La versione 'T extends CharSequence' non viene compilata. https://ideone.com/ySVuPr –

risposta

0

beh questo List<Object> bis = Arrays.asList(Integer.valueOf(1)); ovviamente non viene compilato poiché Arrays.asList(Integer.valueOf(1)) restituirà List<Integer>, è per questo che si ottiene Cannot cast List<Object> to List<T>.

Il secondo caso, eclissi compila assurdamente con T extends CharSequence ma ho controllato con un compilatore online e non si compila, quindi probabilmente è un bug di eclissi.

+0

In effetti, 'Elenco bis = Arrays.asList (Intero. valueOf (1)); 'compila. Nelle versioni precedenti di java veniva compilato solo con un argomento di tipo esplicito 'List bis = Arrays. asList (Integer.valueOf (1)); ', ma ora java ha migliorato l'inferenza del tipo e funziona in entrambi i modi. –

+1

@Paul ur, ho usato jdk7 – Ramanlfc

+0

Questa è la prima risposta e menziona il compilatore di Eclipse come un comportamento anomalo, che sembra essere la conclusione che stavo cercando, nonostante inizialmente credessi di non capire alcune intrinseche del linguaggio. @PaulBoddington ringrazia anche per i vostri preziosi commenti. – gdabski

0

La chiave per comprendere un simile comportamento è capire che cos'è la cancellazione del tipo . Nonostante la credenza popolare che sia rimuove i parametri di tipo in fase di esecuzione - in realtà non funziona esattamente in questo modo. Che cosa fa, lo riduce ai limiti di parametri dichiarati. Quindi ovunque si digiti List<T> dove T ha dei limiti, in realtà viene ridotto a List<[lower-bound-of-T]>. E dal momento che non è un ObjectCharSequence, List<Object> non può essere gettato a List<T> (che significa almeno List<CharSequence>)

Perché questo accade? Immaginate la vostra classe Sandbox ha metodo che accetta parametro di tipo T:

public class Sandbox<T extends CharSequence> { 
    void bar(T param) { 
     //... 
    } 
} 

bar(T) può accettare T 's e T è tutto ciò che si estende CharSequence, in modo sostanzialmente in fase di esecuzione questo funziona efficacemente come

void bar(CharSequence param) { 
    //... 
} 

e quindi non può accettare semplici Object.Ecco perché la semplice limitazione del parametro inferiore non vuoto limita i cast gratuiti da ...<Object>

Inoltre, il parametro jolly ? può semplicemente farti perdere la testa. Dice al compilatore qualcosa come "Non ho idea di cosa sia ma sono abbastanza sicuro che soddisfi tutti i limiti". Abbastanza strano, compreso questo fatto, si può lanciare (quasi?) Qualche cosa ad esso, in modo che rende possibile

List<Object> bis = Arrays.asList(Integer.valueOf(1)); 
    List<T> result = (List<T>) (List<?>) bis; 

Così, quando si tratta di design di classe con i generici, si dovrebbe essere molto, molto attenti.