2010-06-07 6 views
5

L'esecuzione di questo codice:Java HashSet e tipo di dati Breve, incompatibilità?

public class SomeSet { 

    public static void main(String[] args) { 

     Set<Short> s = new HashSet<Short>(); 

     for (short i = 0; i < 100; i++) { 

      s.add(i); 

      s.remove(i - 1); 

     } 

     System.out.println(s.size()); 

    } 

} 

stamperà il valore 100.

Perché si stampa questo valore?

+1

come cosa, vuoi che proviamo ??? – pgras

risposta

10
s.remove(i - 1); 

La riga precedente tenterà di rimuovere Integer oggetti dal set, perché tutti i calcoli interi in Java hanno int (o long) Risultati. Poiché il set contiene oggetti Short, il metodo remove() non avrà alcun effetto.

Questo (e problemi simili) è il motivo principale per cui non si dovrebbe quasi mai usare short (e, più ancora, Short). L'utilizzo di un'implementazione Set per contenere numeri autobox comporta un sovraccarico massiccio (facilmente 1000%), quindi è piuttosto inutile cercare di risparmiare spazio utilizzando Short anziché Integer.

+0

... o 'float' o' double' ;-) –

6

Il problema è che remove(i-1) chiama il metodo remove con un oggetto Integer, poiché i-1 è di tipo int (che ottiene automaticamente inscatolato in un Integer).

Per assicurarsi che si chiama remove con un uso Short oggetto questo:

s.remove((short) (i - 1)); 
+0

O, più esplicitamente s.remove (Short.valueOf (i-1)); –

+0

@Steve: che non verrebbe compilato in quanto sarebbe necessario anche un cast esplicito. Rendendolo più esplicito ma anche più prolisso. –

0

Il tipo di i - 1 è int, quindi diventa autoboxed in un intero.

Normalmente ci si aspetterebbe una raccolta generica per impedire l'esecuzione di operazioni con argomenti del tipo errato, ma l'interfaccia su Set<E> è un po 'allentata.

Poiché il metodo di Set<E>remove prende un Object piuttosto che un E, il compilatore non avvertirà che si sta rimuovendo un tipo diverso da quello che il set contiene.

Per imporre che sia un Short, immettere il valore numerico su (short). (Casting per (Short) non è consentito, e che avrebbe dovuto lanciare il valore numerico da utilizzare Short.valueOf)

0

Si noti che il metodo Add viene genericamente digitato boolean add(E o) così nel tuo caso di Set il metodo add prenderà una breve, mentre il metodo remove non è tipicamente boolean remove(Object o) tipizzato in modo i - 1 autoboxes a un intero. Per qualsiasi valore di i new Short(i).equals(new Integer(i)) sarà sempre falso.

Si noti che se si prova s.add(i - 1); si otterrà un errore del compilatore perché i - 1 diventa un'istanza di Numero intero e i tipi Integer e Short non corrispondono.