Quando usare la classe wrapper e il tipo primitivo


Risposte:


69

Altri hanno menzionato che alcuni costrutti come Collectionsrequire objects e che gli oggetti hanno più overhead rispetto alle loro controparti primitive (memory & boxing).

Un'altra considerazione è:

Può essere utile inizializzare oggetti nullo inviare nullparametri in un metodo / costruttore per indicare lo stato o la funzione. Questo non può essere fatto con le primitive.

Molti programmatori inizializzano i numeri su 0 (impostazione predefinita) o -1 per indicare ciò, ma a seconda dello scenario, ciò potrebbe essere errato o fuorviante.

Questo creerà anche la scena per NullPointerExceptionquando qualcosa viene usato in modo errato, il che è molto più facile da programmare di qualche bug arbitrario su tutta la linea.


15
"Può essere utile inizializzare gli oggetti su null". Non può essere utile perché questo non è corretto, se il campo è facoltativo dovresti indicarlo esplicitamente.
Eddie Jamsession

8
lol @EddieJamsession grazie, non inizializzerò mai più a null. (pfffft)
pstanton

@EddieJamsession Se l'inizializzazione di oggetti su null come un modo per indicare un errore durante l'impostazione del valore effettivo non è riuscita, in quale altro modo proporresti di rilevare questo problema? Oh, mi sono appena reso conto mentre digito questo: eccezioni. Una NullPointerException è troppo generica; sarebbe meglio usare eccezioni personalizzate molto specifiche per indicare cosa è andato storto. Bene, lo farò d'ora in poi ...
klaar

1
@EddieJamsession Dopo aver letto sull'argomento, mi sono imbattuto nel concetto di un oggetto opzionale. Destra.
klaar

18

In generale, dovresti usare i tipi primitivi a meno che tu non abbia bisogno di un oggetto per qualche motivo (ad esempio per metterlo in una raccolta). Anche in questo caso, considera un approccio diverso che non richiede un oggetto se desideri massimizzare le prestazioni numeriche. Ciò è consigliato dalla documentazione e questo articolo dimostra come l'auto-boxing possa causare una grande differenza di prestazioni.


3
il successo in termini di prestazioni non è così grande che la leggibilità / affidabilità del codice dovrebbe passare in secondo piano.
pstanton

2
In primo luogo, l'utilizzo appropriato delle primitive non renderà il codice illeggibile. In secondo luogo, in alcuni casi il calo delle prestazioni è significativo. È assurdo dire che non lo è mai.
Matthew Flaschen

1
@pstanton: per favore spiega come Integerè più leggibile di int.
Stephen C

In molti casi Integer non è più leggibile di int e in questi casi userò sempre int, o se so che una certa variabile non sarà MAI nulla, userò int perché int è come hai sottolineato leggermente più efficiente. Tuttavia, in molti casi è più facile per un altro programmatore comprendere lo stato di una variabile quando viene utilizzato un oggetto, poiché può essere inizializzato a null per indicare che non è pronto. Ad esempio, se si dispone di un record di database non salvato che ha un ID numerico incrementale univoco, questo ID dovrebbe essere 0, -1 o null prima che gli venga assegnato un ID valido? In quel caso gli oggetti sono migliori.
pstanton

per quanto riguarda le prestazioni - in casi speciali, il calo delle prestazioni può essere significativo, ad esempio se stai creando una moltitudine di questi Oggetti molto rapidamente o se molti molti molti di essi si accumulano in un periodo di tempo. Tuttavia, mi aspetto che un programmatore decente sia in grado di identificare questi casi speciali da evitare o da modificare di conseguenza. Non ho mai detto che non sia MAI significativo, ma in generale non lo è.
pstanton

12

A mio parere, se i membri della mia classe sono variabili wrapper, non si basa sui valori predefiniti, che è un comportamento amichevole per gli sviluppatori.

1.

class Person {
   int SSN ; // gets initialized to zero by default 
}

2.

class PersonBetter {
  Integer SSN; //gets initialized to null by default
}

Nel primo caso, non è possibile mantenere il valore SSN non inizializzato. Potrebbe far male se non stai controllando se il valore è stato impostato prima di tentare di usarlo.

Nel secondo caso, puoi mantenere SSN inizializzato con null. Ciò può portare a NullPointerException ma è meglio che inserire inconsapevolmente valori predefiniti (zero) come SSN nel database ogni volta che si tenta di utilizzarlo senza inizializzare il campo SSN.


3
Il modello builder ha lo scopo di aggirare questo problema. In questo scenario, crei PersonBuilderun'eccezione se SSN non è impostato prima di chiamare "build" per ottenere l' Personistanza. Penso che questo genere di cose sia eccessivo, ma è ciò che il linguaggio Java promuove per i modelli appropriati.
Sandy Chapman,

8

Userei solo i tipi di wrapper se necessario.

Usandoli non guadagni molto, oltre al fatto che lo sono Objects.

E perdi il sovraccarico nell'utilizzo della memoria e nel tempo trascorso a boxare / unboxing.


4
potresti non guadagnare molto, ma non perdi neanche molto. a meno che tu non stia correndo su un palmare degli anni '90.
pstanton

Il fatto che siano oggetti dà loro anche molto più contesto e incapsulamento rispetto a una semplice primitiva. Quindi potresti effettivamente guadagnare molto a seconda di cosa sono destinate a quelle primitive e dove vengono utilizzate.
aberrant80

4

Praticamente mi ero imbattuto in una situazione in cui è possibile spiegare l'uso della classe wrapper.

Ho creato una classe di servizio che aveva una longvariabile di tipo

  1. Se la variabile è di tipo long- quando non è inizializzata, sarà impostata su 0 - questo creerà confusione per l'utente quando visualizzato nella GUI
  2. Se la variabile è di tipo Long- quando non è inizializzata, verrà impostata su null- questo valore nullo non verrà visualizzato nella GUI.

Questo vale anche per i casi Booleanin cui i valori possono essere più confusi quando usiamo primitiva boolean(poiché il valore predefinito è falso).


3

Le collezioni sono il caso tipico per i semplici oggetti wrapper Java. Tuttavia, potresti considerare di dare al wrapper un significato più specifico nel codice (oggetto valore).

IMHO c'è quasi sempre un vantaggio nell'usare oggetti valore quando si riduce alla leggibilità e alla manutenzione del codice. Il wrapping di semplici strutture di dati all'interno di oggetti quando hanno determinate responsabilità spesso semplifica il codice. Questo è qualcosa di molto importante nella progettazione guidata dal dominio .

Ovviamente c'è il problema delle prestazioni, ma tendo a ignorarlo fino a quando non ho la possibilità di misurare le prestazioni con dati adeguati e fare azioni più dirette verso l'area problematica. Potrebbe anche essere più semplice comprendere il problema delle prestazioni se anche il codice è di facile comprensione.


3

le prestazioni di applicazioni dominate da calcoli numerici possono trarre grandi vantaggi dall'uso delle primitive.

tipi primitivi, si usa l'operatore ==, ma per il wrapper la scelta preferita è chiamare il metodo equals ().

"Tipi primitivi considerati dannosi" perché mescolano "semantica procedurale in un modello orientato agli oggetti altrimenti uniforme.

Molti programmatori inizializzano i numeri su 0 (impostazione predefinita) o -1 per indicare ciò, ma a seconda dello scenario, ciò potrebbe essere errato o fuorviante.


1

Se vuoi usare le collezioni, devi usare le classi wrapper.

I tipi primitivi vengono utilizzati per gli array. Inoltre, per rappresentare dati privi di comportamento, ad esempio un contatore o una condizione booleana.

Dall'autoboxing, la frontiera del "quando usare primitivo o wrapper" è diventata piuttosto confusa.

Ma ricorda, i wrapper sono oggetti, quindi ottieni tutte le fantastiche funzionalità di Java. Ad esempio, puoi usare reflexion per creare oggetti Integer, ma non valori int. Le classi wrapper hanno anche metodi come valueOf.


Oltre alle raccolte, non dovrei usare classi wrapper? Che ne dici di usarlo per dichiarazioni ordinarie come Integer i = new Integer (10); È bene fare così?
Gopi

l'autoboxing ti permette di fare Integer i = 10;
Tom

1
No, Sri. Se non hai il requisito che io sia un oggetto, non renderlo tale.
Matthew Flaschen

L'autoboxing disimballerà quanto sopra dichiarato i in int i = 10 o Integer i = 10?
Gopi

3
int pi = new Integer (10); lavori. Intero oi = 10; lavori. int ni = null; non funziona. l'LHS viene convertito in qualsiasi cosa richieda l'RHS.
pstanton

0

Se vuoi creare un tipo di valore. Qualcosa come ProductSKU o AirportCode.

Quando un tipo primitivo (stringa nei miei esempi) definisce l'uguaglianza, ti consigliamo di sovrascrivere l'uguaglianza.


5
la stringa non è primitiva
pstanton

2
ci sono ancora buone ragioni per racchiudere un tipo di valore che contiene una stringa come oggetto di base.
Chris Missal

la tua risposta non ha senso. non sono sicuro di quello che stai dicendo. Sono d'accordo con il tuo commento però, le classi wrapper sono una buona idea se migliorano la leggibilità.
pstanton

I tipi di valore o gli oggetti valore devono essere creati ed essere immutabili. Ad esempio, non avrebbe senso creare un oggetto "CountryCode" come: new CountryCode ("USA") quindi creare un altro oggetto allo stesso modo, dove in seguito saranno diversi. Sono solo stringhe per cominciare, ma hanno un significato dietro di loro. Usando le stringhe, puoi modificarle (aggiungendo più dati, ecc.) Ma non sarebbero più uguali. Vedi questo articolo per una migliore descrizione di ciò che sto cercando di spiegare :) Spero che abbia senso c2.com/cgi/wiki?ValueObject
Chris Missal

0

I valori primitivi in ​​Java non sono oggetto. Per manipolare questi valori come oggetti, il pacchetto java.lang fornisce una classe wrapper per ciascuno dei tipi di dati primitivi.

Tutte le classi di wrapper sono definitive. L'oggetto di tutte le classi wrapper che possono essere avviate non sono modificabili, il che significa che il valore nell'oggetto wrapper non può essere modificato.

Tuttavia , la classe void è considerata una classe wrapper ma non racchiude alcun valore primitivo e non è inizializzabile. Non ha un costruttore pubblico, denota semplicemente un oggetto classe che rappresenta la parola chiave void.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.