primitive tipo byte - Perché le persone usano ancora i tipi primitivi in Java?





9 Answers

L'autoboxing può portare a NPE difficili da individuare

Integer in = null;
...
...
int i = in; // NPE at runtime

Nella maggior parte delle situazioni, l'assegnazione nullo a in è molto meno ovvia di quanto sopra.

variabili float int

Dal momento che Java 5, abbiamo avuto boxing / unboxing di tipi primitivi in ​​modo che int sia wrapper per essere java.lang.Integer , e così e così via.

Ultimamente vedo molti nuovi progetti Java (che richiedono sicuramente un JRE di almeno la versione 5, se non 6) che usano int piuttosto che java.lang.Integer , sebbene sia molto più comodo usare quest'ultimo, dato che ha alcuni metodi di supporto per la conversione in valori long et al.

Perché alcuni usano ancora i tipi primitivi in ​​Java? C'è qualche vantaggio tangibile?




I tipi di box hanno prestazioni peggiori e richiedono più memoria.




Puoi davvero immaginare un?

  for (int i=0; i<10000; i++) {
      do something
  }

loop con java.lang.Integer invece? Un java.lang.Integer è immutabile, quindi ogni incremento attorno al ciclo creerebbe un nuovo oggetto java sull'heap, invece di incrementare l'int nello stack con un'unica istruzione JVM. La performance sarebbe diabolica.

Non sarei affatto d'accordo sul fatto che sia molto più comodo usare java.lang.Integer di int. Anzi. Autoboxing significa che puoi usare int dove altrimenti saresti costretto a usare Integer, e il compilatore java si occuperà di inserire il codice per creare il nuovo oggetto Integer per te. Autoboxing consente di utilizzare un int dove è previsto un intero, con il compilatore che inserisce la costruzione dell'oggetto pertinente. In nessun modo rimuove o riduce la necessità di int in primo luogo. Con l'autoboxing ottieni il meglio da entrambi i mondi. Si ottiene automaticamente un intero creato automaticamente quando si ha bisogno di un oggetto java basato su heap e si ottiene la velocità e l'efficienza di un int quando si eseguono calcoli aritmetici e locali.




Prima di tutto, abitudine. Se hai codificato in Java per otto anni, accumuli una considerevole quantità di inerzia. Perché cambiare se non ci sono motivi validi per farlo? Non è come se usare i primitivi inscatolati abbia qualche vantaggio in più.

L'altro motivo è affermare che null non è un'opzione valida. Sarebbe inutile e fuorviante dichiarare la somma di due numeri o una variabile di ciclo come Integer .

C'è anche l'aspetto delle prestazioni, mentre la differenza di prestazioni non è critica in molti casi (anche se è pessima), a nessuno piace scrivere codice che possa essere scritto altrettanto facilmente in un modo più veloce che siamo già abituato a.




Non posso credere che nessuno abbia menzionato ciò che ritengo sia la ragione più importante: "int" è così, molto più facile da digitare di "Integer". Penso che la gente sottovaluti l'importanza di una sintassi sintetica. Le prestazioni non sono davvero un motivo per evitarle perché la maggior parte delle volte in cui si utilizzano numeri è negli indici di loop e l'incremento e il confronto di tali costi non si risolve in alcun ciclo non banale (indipendentemente dal fatto che si utilizzi int o Integer).

L'altro motivo è dato dal fatto che è possibile ottenere NPE ma è estremamente facile da evitare con i tipi di box (e si garantisce che sia evitato finché si inizializzano sempre su valori non nulli).

L'altra ragione era che (new Long (1000)) == (new Long (1000)) è falso, ma questo è solo un altro modo per dire che ".equals" non ha supporto sintattico per i tipi di box (a differenza degli operatori <,> , =, ecc.), quindi torniamo alla ragione "sintassi più semplice".

Penso che l'esempio di loop non primitivo di Steve Yegge illustri molto bene il mio punto: http://sites.google.com/site/steveyegge2/language-trickery-and-ejb

Pensa a questo: con che frequenza usi i tipi di funzione in linguaggi che hanno una buona sintassi per loro (come qualsiasi linguaggio funzionale, python, ruby ​​e anche C) rispetto a java dove devi simularli usando interfacce come Runnable e Callable e classi senza nome.




Oltre a ciò che altri hanno detto, le variabili locali primitive non vengono allocate dall'heap, ma invece nello stack. Ma gli oggetti sono allocati dall'heap e quindi devono essere raccolti.




È difficile sapere che tipo di ottimizzazioni stanno accadendo sotto le coperte.

Per uso locale, quando il compilatore ha abbastanza informazioni per fare ottimizzazioni escludendo la possibilità del valore nullo, mi aspetto che le prestazioni siano le stesse o simili .

Tuttavia, le matrici di primitivi sono apparentemente molto diverse dalle raccolte di primitivi inscatolati. Questo ha senso dato che pochissime ottimizzazioni sono possibili in profondità all'interno di una collezione.

Inoltre, Integer ha un sovraccarico logico molto più alto rispetto a int : ora devi preoccuparti se int a = b + c; lancia un'eccezione

Userei le primitive il più possibile e mi affido ai metodi di fabbrica e all'autoboxing per darmi i tipi di box più semanticamente potenti quando sono necessari.




int loops = 100000000;

long start = System.currentTimeMillis();
for (Long l = new Long(0); l<loops;l++) {
    //System.out.println("Long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around Long: "+ (System.currentTimeMillis()- start));

start = System.currentTimeMillis();
for (long l = 0; l<loops;l++) {
    //System.out.println("long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around long: "+ (System.currentTimeMillis()- start));

Millisecondi portati a ciclo '100000000' volte su Long: 468

Millisecondi portati a ciclo '100000000' volte intorno a lungo: 31

In una nota a margine, non mi dispiacerebbe vedere qualcosa di simile trovare in Java.

Integer loop1 = new Integer(0);
for (loop1.lessThan(1000)) {
   ...
}

Dove il ciclo for incrementa automaticamente loop1 da 0 a 1000 o

Integer loop1 = new Integer(1000);
for (loop1.greaterThan(0)) {
   ...
}

Dove il ciclo for decrementa automaticamente il loop1 da 1000 a 0.




1) Hai bisogno di primitive per fare operazioni matematiche 2) I primitivi richiedono meno memoria come risposta sopra e prestazioni migliori

Dovresti chiedere perché è richiesto il tipo di classe / oggetto

La ragione per avere il tipo di oggetto è semplificarci la vita quando gestiamo le raccolte. Le primitive non possono essere aggiunte direttamente a List / Map, ma è necessario scrivere una classe wrapper. Il tipo di classi Readymade Integer ti aiuta qui in più ha molti metodi di utilità come Integer.pareseInt (str)




Related