Le variabili per gli oggetti contengono l'indirizzo di un oggetto.
Possono anche contenere il valore null
Indica che un oggetto non esiste.
Quando readLine viene invocato su un file che è finito, ritorna null
String s; while(true) { s=b.readLine(); if(s==null) break; System.out.println(s); }
Non è un oggetto.
È un valore speciale che viene scritto nella variabile.
Se s è una stringa (es. dopo s="abcd"):
Se s vale null (es. dopo s=null;):
Attenzione: null non indica la stringa vuota.
La stringa vuota è un oggetto.
La stringa vuota è una sequenza di caratteri di lunghezza zero.
Il valore null indica che non c'è un oggetto:
Il valore di ritorno di b.readLine() indica:
Pensate a null come al valore "nessun indirizzo".
Si tratta sempre di un valore numerico, però non indica un indirizzo.
In altri linguaggi, ò il valore 0 (e nessun oggetto può essere memorizzato all'indirizzo 0)
Una variabile per un oggetto contiene null oppure un indirizzo.
Se contiene un indirizzo, allora è l'indirizzo dell'oggetto. Altrimenti, l'oggetto non esiste.
Si può usare per qualsiasi oggetto:
Point p; p=null;
Se in p ci metto null, non devo creare l'oggetto.
Point p; p=new Point(); p=null;
Primo: viene creata la variabile:
Viene creato l'oggetto, e il suo indirizzo va in p.
Viene messo dentro p
Si è perso l'indirizzo dell'oggetto.
L'oggetto non si può usare.
Verrà cancellato automaticamente.
Point p; p=new Point(); p=null;
Non serve creare un oggetto, se poi nella variabile ci metto null
La costante null la posso mettere in una qualsiasi variabile oggetto:
Studente s; s=null;
Cosa succede se uso una componente o un metodo?
Le componenti e i metodi riguardano gli oggetti:
null indica che l'oggetto non esiste
Point p; p=null; p.x=12; // errore: non esiste l'oggetto p p.move(10,2); // stesso errore
Stessa regola vista finora: non posso usare le componenti o invocare i metodi se l'oggetto non esiste.
Se faccio p=null l'oggetto non esiste.
Point p; if(p==null) ...
Qui p vale null?
No! La variabile non è inizializzata.
L'errore è diverso: p non contiene un valore preciso.
p=null; ... if(p==null) ...
Se faccio l'assegnamento p=null; allora p contiene il valore null
L'oggetto non esiste, ma p contiene un valore specifico.
Quindi, si può confrontare il valore di p con null (anche se l'oggetto non esiste).
Le variabili non vengono inizializzate automaticamente.
Le componenti degli oggetti vengono inizializate a 0 se numeriche e a null se di tipo oggetto.
Il compilatore non rileva errori.
Però questo può portare a errori.
Controllare sempre l'inizializzazione.
Cosa succede quando si esegue questo programma?
import java.awt.*; class NullMet { static void azzera(Point q) { q.x=0; q.y=0; } public static void main(String args[]) { Point p; p=null; azzera(p); System.out.println(p); } }
Exception in thread "main" java.lang.NullPointerException at NullMet.azzera(NullMet.java:5) at NullMet.main(NullMet.java:13)
L'errore indica che è stata usata una componente, oppure invocato un metodo, di un oggetto che non esiste.
Inizialmente:
Se faccio q=p; viene copiato l'indirizzo scritto in p dentro q.
Lo stesso succede quando si invoca il metodo.
Il valore null viene copiato.
Si cerca di fare q.x=0; quando non esiste l'oggetto.
Si genera un errore.
Domanda: cosa stampa questo programma?
import java.awt.*; class Modifica { static void cambia(Point q) { q=new Point(); q.move(0,0); } public static void main(String args[]) { Point p; p=null; cambia(p); System.out.println(p.x); } }
Bisogna vedere cosa succede in memoria.
Inizio:
Viene creata la zona di memoria associata.
Vengono copiati i valori nelle variabili.
Viene creato un nuovo oggetto.
Il suo indirizzo viene messo in q
La zona di memoria del metodo viene cancellata.
L'oggetto esiste ancora, ma non è più accessibile.
Verrà distrutto automaticamente.
p è sempre rimasto null
Quando si cerca di stampare p.x, si genera un errore.
Regola generale:
quando si invoca un metodo, sono i valori che vengono trasmessi al metodo
Quando si fa cambia(p), questo equivale a cambia(null)
Perchè cambia(null) dovrebbe modificare p?
Tutti i metodi possono modificare/usare gli oggetti, basta che abbiano il loro indirizzo.
Se un metodo riceve l'indirizzo di un oggetto, lo può modificare.
Il metodo riceve comunque un valore
Dal valore può risalire all'oggetto e cambiarlo.