2015-01-30 11 views
8

Perché è possibile inserire un String in un List<Integer> nel seguente codice? Ho una classe che inserisce numeri in una lista di interi:Perché non aggiungere (stringa) su un elenco <Integer> passato a un parametro Elenco per generare un'eccezione?

public class Main {  
    public static void main(String[] args) {   
     List<Integer> list = new ArrayList<Integer>(); 
     list.add(2); 
     list.add(3); 
     list.add(4); 

     Inserter inserter = new Inserter(); 
     inserter.insertValue(list); 
     System.out.print(list);   
    } 
} 

Poi ho una classe separata che inserisce un String in un List, con il valore stringa numerica "42":

public class Inserter {  
    void insertValue(List list) 
    { 
     list.add(new String("42")); 
    } 
} 

Perché il compilatore non genera un errore del compilatore o il runtime genera un'eccezione di runtime come *CastException, quando aggiungo il String all'elenco di numero intero? Inoltre, perché lo System.out.print(list) produce output come il seguente senza generare eccezioni?

[2, 3, 4, 42] 

Qual è la ragione fondamentale che consente a tutto questo di accadere?

+3

che un'eccezione compilatore cosa si aspetta? –

+1

Da dove hai preso il codice? La mia ipotesi è che il punto sia spiegare come vengono passati gli argomenti in Java, osservando che è un * riferimento * alla lista che viene passata al metodo (in base al valore), non una copia dell'oggetto lista. O forse è pensato per dimostrare i tipi non elaborati. Non è del tutto chiaro dove ti aspetteresti un errore. Potresti chiarire la domanda per favore? –

+2

Penso che sia confuso su come un 'new String (" 42 ")' può essere inserito in un valore che è stato originariamente dichiarato come 'Elenco '. – August

risposta

8

Questo è probabilmente un esempio per illustrare type erasure per i generici (consiglio di leggere quel collegamento per comprendere appieno questo e il ruolo cruciale che svolge nei generici di Java).

  1. list è dichiarata come List<Integer>
  2. Quando è passato come argomento per listValue è cast un raw type
  3. Da questo punto in poi, in che modo il programma in fase di esecuzione non è a conoscenza che in origine era una "lista di numeri interi", quindi può inserire qualsiasi oggetto senza eccezioni - all'interno della dichiarazione di classe la variabile di tipo viene cancellata a Object
  4. Nel metodo principale il comando print chiama semplicemente toString nell'elenco, che non si preoccupa di ciò che contiene e quindi stampa gli elementi inclusa la stringa.

Se volete vedere un'eccezione, prova ad aggiungere una riga:

Integer myInt = list.get(3); // try to get the string 

Questo lancerà una ClassCastException come il compilatore, durante la cancellazione, inserti in calchi, ove necessario, per proteggere la sicurezza tipo.

calchi di tipi parametrici, come ad esempio List<Integer> al tipo grezzo, come ad esempio List, si invia un avviso del compilatore per dirvi che proprio questo tipo di problema potrebbe essere in procinto di accadere. È possibile sopprimere questo avviso con @SuppressWarnings("unchecked") (o "rawtypes", se è available to you). Questo è un buon modo per "riconoscere" che stai per fare qualcosa che porterà a un'eccezione di runtime non controllata, e aiuta anche a dire ad altri programmatori futuri che potrebbe succedere qualcosa di funky. Es .:

void insertValue(@SuppressWarnings("unchecked") List list) 
{ 
    list.add(new String("42")); 
} 
+1

Vorrei aggiungere che la modifica di 'void insertValue (List list)' a void insertValue (Lista lista) 'produrrebbe un errore e darebbe l'eccezione del compilatore – ZqBany

+0

@ZqBany. Non sono sicuro che sia rilevante qui, quindi lo lascio fuori. Il punto di quel campione è quello di illustrare i tipi grezzi e come possono aggirare la sicurezza del tipo. La modifica del parametro del metodo in un tipo parametrizzato annullerebbe l'oggetto del campione. Se qualcuno scrive i propri metodi generici, si spera che non usino mai i tipi non elaborati. –

+0

Penso solo che questo è un comportamento previsto da java_user, che il compilatore dovrebbe lanciare un'eccezione al punto di provare ad aggiungere String a List of Integers. E aggiungere questa piccola informazione su come ottenere quel comportamento potrebbe essere utile, ma ovviamente questo sarà un metodo diverso e per alcuni potrebbe essere irreversibile – ZqBany

0

Il compilatore getterà

Exception in thread java.lang.ClassCastException "principale": java.lang.String non può essere gettato a java.lang.Integer 234 a com.performance.Main.main (Main.java:26)

come è stato specificato il tipo qui ArrayList<Integer>(); e quando si aggiunge una stringa list.add(new String("42"));

+0

@Down voter puoi commentare? –

+1

Non è chiaro cosa stai dicendo. Il compilatore non genera un'eccezione, il runtime lo fa. Anche in base al codice dell'OP, nessuna eccezione verrà lanciata in fase di runtime. Perché pensi che sarebbe? –

Problemi correlati