1. Variabili di riferimento
Nel linguaggio Java ci sono due tipi di variabili: variabili primitive e tutto il resto. Si dà il caso che ora parleremo di "tutto il resto".
Sarebbe infatti più corretto dire che esistono variabili primitive e variabili di riferimento . Quindi quali sono queste variabili di riferimento?
A differenza dei tipi primitivi, le cui variabili memorizzano direttamente i valori, le variabili di riferimento memorizzano i riferimenti agli oggetti. Cioè, c'è un oggetto da qualche parte in memoria e la variabile di riferimento memorizza semplicemente l'indirizzo di questo oggetto in memoria (un riferimento all'oggetto).
Solo i tipi primitivi memorizzano i valori direttamente all'interno delle variabili. Tutti gli altri tipi memorizzano solo un riferimento all'oggetto . A proposito, hai già incontrato due di questi tipi di variabili: String
variabili e variabili di matrice .
Sia un array che una stringa sono oggetti archiviati da qualche parte nella memoria. String
le variabili e le variabili array memorizzano solo i riferimenti agli oggetti.
int a, int b and double d
sono variabili primitive che memorizzano i loro valori al loro interno.
Una String str
variabile è un riferimento e memorizza l'indirizzo (riferimento) di un String
oggetto in memoria.
Quando si assegna un valore primitivo a una variabile di tipo primitivo, il suo valore viene copiato (duplicato). Quando si assegna una variabile di riferimento, viene copiato solo l'indirizzo dell'oggetto — l'oggetto stesso non viene copiato .
2. Cosa sono i riferimenti?
Qual è la differenza fondamentale tra variabili di riferimento e variabili primitive?
Una variabile primitiva è come una scatola: puoi memorizzare un valore in essa. Una variabile di riferimento è più simile a un pezzo di carta con sopra un numero di telefono.
Una macchina contro le chiavi della macchina
Immagina di decidere di regalare un'auto al tuo amico per il suo compleanno. Non lo avvolgerai in una scatola e lo porterai con te: l'auto è troppo grande per quello.
È molto più conveniente presentare solo le chiavi della macchina in una scatola abbastanza grande da contenerle. Il tuo amico capirà tutto quando tirerà fuori le chiavi dalla scatola. Non c'è bisogno di portare con sé l'intera vettura, basta consegnare le chiavi.
Una persona contro il suo numero di telefono
Oppure ecco un altro paragone: una persona e il suo numero di telefono. Un numero di telefono non è la persona, ma un numero di telefono può essere utilizzato per chiamarla, chiederle informazioni o fornire istruzioni.
Allo stesso modo, un riferimento viene utilizzato per interagire con un oggetto. Tutti gli oggetti interagiscono tra loro utilizzando i riferimenti. Invece di "scambiare persone", scambiamo semplicemente i numeri di telefono.
Quando si assegna un valore a una variabile primitiva, il suo valore viene copiato (duplicato). Quando si assegna un valore a una variabile di riferimento, viene copiato solo l'indirizzo (numero di telefono) dell'oggetto, l'oggetto stesso non viene copiato.
Un riferimento offre un ulteriore vantaggio: puoi passare un riferimento a un oggetto a un metodo e il metodo sarà in grado di modificare (cambiare) l'oggetto utilizzando il riferimento ad esso, chiamando i suoi metodi e accedendo ai dati all'interno dell'oggetto.
3. Assegnazione delle referenze
Quando si assegnano variabili di riferimento, viene assegnato solo l'indirizzo dell'oggetto in memoria. Gli oggetti stessi non appaiono né scompaiono.
Questo approccio evita di copiare grandi quantità di memoria. Se devi passare un oggetto molto grande a un metodo, passiamo semplicemente il riferimento all'oggetto e il gioco è fatto. Il riferimento occupa molto meno spazio.
La dimensione di tutte le variabili di riferimento (indipendentemente dal loro tipo) è la stessa: 4 byte (come un int). Ma! Se la tua applicazione è in esecuzione su una macchina Java a 64 bit, tutti i riferimenti avranno una dimensione di 8 byte (64 bit).
Inoltre, le referenze possono essere assegnate solo l'una all'altra. Non è possibile modificare i riferimenti o assegnare valori arbitrari alle variabili di riferimento:
Codice | Descrizione |
---|---|
|
Questo è permesso |
|
Ma questo non è permesso |
|
E questo non è permesso |
4. Un null
riferimento
E cosa memorizza una variabile di riferimento se non le è stato ancora assegnato nulla?
Memorizza un riferimento nullo . null
è una parola chiave Java speciale che indica l'assenza di un riferimento (un riferimento vuoto). Il null
valore può essere assegnato a qualsiasi variabile di riferimento.
Tutte le variabili di riferimento lo sono null
a meno che non abbiano avuto un qualche tipo di riferimento assegnato loro.
Esempi:
Codice | Descrizione |
---|---|
|
La String name variabile ha un valore predefinito: null . La int age variabile ha un valore predefinito: 0 . |
Le variabili locali a cui non è stato assegnato un valore sono considerate non inizializzate sia per i tipi primitivi che per i tipi di riferimento.
Se una variabile memorizza un riferimento a un oggetto e desideri cancellare il valore della variabile, assegnale semplicemente un riferimento nullo.
Codice | Descrizione |
---|---|
|
s negozi null . s memorizza un riferimento a un oggetto stringa s memorizza null . |
5. Passaggio di riferimenti ai metodi
Se un metodo ha parametri che sono tipi di riferimento , i valori vengono passati al metodo nello stesso modo in cui si lavora con variabili non di riferimento. Al parametro viene semplicemente assegnato il valore dell'altra variabile.
Esempio:
Codice | Descrizione |
---|---|
|
riempie fill l'array passato ( array ) con il valore passato ( value ). |
Quando fill
viene chiamato il metodo, al array
parametro viene assegnato un riferimento all'array data
. Alla value
variabile viene assegnato un riferimento all'oggetto stringa ("Ciao").
Ecco come appare la memoria prima di chiamare il fill
metodo:
Ecco come appare la memoria quando il fill
metodo è in esecuzione :

Le variabili data
e array
si riferiscono a (memorizzano riferimenti a) lo stesso contenitore in memoria.
La value
variabile memorizza un riferimento all'oggetto stringa ( "Hello"
).
Le celle dell'array memorizzano solo i riferimenti all'oggetto "Hello"
.
In effetti, nessun oggetto viene duplicato, vengono copiati solo i riferimenti.
6. Confronto con il linguaggio C/C++
Nelle interviste, a volte ai programmatori Java viene chiesto come i dati vengono passati ai metodi in Java? E a volte la domanda è se i dati vengono passati per riferimento o per valore?
Questa domanda viene da C++, ma non è molto significativa in Java . In Java, ai parametri vengono sempre semplicemente assegnati i valori degli argomenti. Quindi la risposta corretta sarebbe " per valore ".
Ma preparati a spiegare la tua posizione , poiché potresti sentire immediatamente la replica: "i tipi primitivi vengono passati per valore e i tipi di riferimento vengono passati per riferimento".
Questa origine di questo problema deriva dal fatto che molti programmatori Java erano programmatori C++ in passato. In quel linguaggio di programmazione, la questione di come i parametri vengono passati ai metodi era molto importante.
In Java, tutto è inequivocabile: i tipi primitivi memorizzano valori e anche i tipi di riferimento memorizzano un valore, un riferimento. Si tratta di stabilire se una variabile è considerata un valore .
In C++, una variabile può memorizzare sia un riferimento a un oggetto sia l'oggetto stesso. Lo stesso valeva per i tipi primitivi: una variabile primitiva poteva memorizzare un valore o dichiarare la variabile come riferimento a un oggetto int
. Quindi, per evitare confusione, i programmatori C++ fanno sempre riferimento all'oggetto a un riferimento come riferimento e all'oggetto stesso come valore.
In C++, potresti facilmente avere la situazione in cui una variabile contiene un oggetto, ma l'altra contiene un riferimento a quell'oggetto. Di conseguenza, la questione di cosa memorizza una variabile - l'oggetto stesso o solo un riferimento ad esso - era molto importante. Quando un oggetto veniva passato a un metodo, veniva copiato (se passato per valore) e non copiato (se passato per riferimento).
In Java, questa dualità non esiste, quindi la risposta corretta è: gli argomenti vengono passati ai metodi Java per valore . È solo che quando parliamo di variabili di riferimento, questo valore è un riferimento.
GO TO FULL VERSION