2010-09-24 17 views
96

Ho visto questa linea in un metodo di classe e la mia prima reazione è stata di mettere in ridicolo lo sviluppatore che lo ha scritto .. Ma poi, ho pensato che dovevo assicurarmi di avere ragione prima.Può "questo" essere mai nullo in Java?

public void dataViewActivated(DataViewEvent e) { 
    if (this != null) 
     // Do some work 
} 

Sarà quella linea sempre valutare a false?

+99

Sempre ridicolizzare prima e chiedere più tardi. È più facile scusarsi che riprendere un'occasione d'oro per abbattere qualcuno in una raffica di zolfo. –

+0

Anch'io l'ho pensato ... In realtà dovevo controllare le annotazioni per assicurarmi che non fosse mio ... Quante volte ho scritto: –

+5

+1 per il termine "raffica di zolfo". –

risposta

78

No, non è possibile. Se stai usando this, allora sei nell'istanza, quindi this non è nullo.

Il JLS dice:

Quando usato come espressione primaria, la parola chiave this indica un valore che è un riferimento all'oggetto per il quale è stato richiamato il metodo istanza (§15.12), o all'oggetto in costruzione.

Se è stato richiamato un metodo da un oggetto, l'oggetto esiste o si avrebbe un NullPointerException prima (o si tratta di un metodo statico, ma poi, non è possibile utilizzare this in esso).


Risorse:

+0

Usando, tuttavia, non riesce a compilare. Se viene compilato, è sicuro da usare. –

+0

È semplicemente assurdo fare un tale controllo o è effettivamente impedito dal linguaggio Java che una cosa del genere possa accadere? I.e è l'eccezione puntatore nullo lanciata prima di entrare nel metodo o solo quando si tenta di accedere a un membro? In situazioni analoghe in altri linguaggi (in particolare C++), questo caso è un comportamento indefinito e il linguaggio non impedirà attivamente tale scenario. –

+4

Non conosco bene Java, ma in C++ il 'this' di un metodo di istanza potrebbe essere NULL. Quindi non sono del tutto convinto che questo sia un motivo sufficiente in Java. – kennytm

57

E 'come se stessi chiedendo "Sono io vivo?" this non può mai essere nullo

+38

_am_ I alive ?! o dio non lo so più – Claudiu

+7

Cogito ergo sum –

+7

In somma ... –

3

No. Per chiamare un metodo di un'istanza di una classe, l'istanza deve esistere. L'istanza viene passata implicitamente come parametro al metodo, con riferimento a this. Se this era null allora non ci sarebbe stata alcuna istanza per chiamare un metodo di.

2

In metodi di classi statiche, this non è definito poiché this è associato a istanze e non classi. Credo che darebbe un errore del compilatore per tentare di usare la parola chiave this nel contesto statico.

7

se si compila con -target 1.3 o precedente, un esternathis possono essere null. O almeno lo era ...

+2

Immagino che attraverso il riflesso possiamo impostare l'esterno su null. potrebbe essere uno scherzo di pesce d'aprile su qualcuno quando ha ottenuto un'eccezione di puntatore nullo nel fare riferimento a "Outer.this.member' – irreputable

1

Quando si richiama un metodo su null riferimento, lo NullPointerException verrà generato da Java VM. Questo è in base alle specifiche, quindi se la VM Java è strettamente conforme alle specifiche, this non sarà mai null.

0

tl; dr, "questo" può essere chiamato solo da un metodo non statico e tutti sappiamo che un metodo non statico viene chiamato da una sorta di oggetto che non può essere nullo.

3

Non è sufficiente che il linguaggio lo imponga. La VM ha bisogno di rafforzarla. A meno che la VM non lo imponi, potresti scrivere un compilatore che non impone il controllo Null prima di chiamare il metodo scritto in Java. Gli opcode per una chiamata al metodo di istanza includono il caricamento di questo riferimento sullo stack, vedere: http://java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14787.In caso contrario, il test risulterebbe falso

7

No mai, la parola chiave 'questo' rappresenta di per sé l'istanza (oggetto) corrente di quella classe nell'ambito di quella classe, con la quale si può accedere a tutti i suoi campi e membri (compresi i costruttori) e quelli visibili della sua classe genitore.

E, cosa ancor più interessante, provare con un valore:

this = null; 

pensate? Com'è possibile, non sarà come tagliare il ramo su cui sei seduto. Dal momento che la parola chiave 'this' è disponibile nell'ambito della classe quindi non appena dici this = null; ovunque all'interno della classe, in sostanza, stai chiedendo a JVM di liberare la memoria assegnata a quell'oggetto nel corso di qualche operazione che JVM non può consentire di accadere in quanto deve tornare indietro in modo sicuro dopo aver terminato l'operazione.

Inoltre, il tentativo di this = null; comporterà l'errore del compilatore. La ragione è piuttosto semplice, una parola chiave in Java (o qualsiasi altra lingua) non può mai essere assegnata ad un valore, ad esempio una parola chiave non può mai essere il valore sinistro di un'operazione di assegnazione.

Altri esempi, non si può dire:

true = new Boolean(true); 
true = false; 
+0

Buona spiegazione amico. –

+0

@PankajSharma Grazie :) – sactiw

+0

Ho trovato questo perché volevo vedere se potevo usare 'this = null'. La mia istanza era in Android, dove volevo rimuovere una vista e impostare l'oggetto che gestiva la vista su null. Quindi volevo utilizzare un metodo 'remove()' che rimuoveva la vista effettiva e quindi l'oggetto handler sarebbe reso inutilizzabile, quindi volevo annullarlo. – Yokich

0

Un normale this può mai essere null nel codice reale Java , e il vostro esempio utilizza un normale this. Vedi le altre risposte per maggiori dettagli.

Un qualificato thisdovrebbe mai esserenull, ma è possibile rompere questo. Si consideri il seguente:

public class Outer { 
    public Outer() {} 

    public class Inner { 
     public Inner() {} 

     public String toString() { 
      return "outer is " + Outer.this; // Qualified this!! 
     } 
    } 
} 

Quando vogliamo creare un'istanza di Inner, abbiamo bisogno di fare questo:

public static void main(String[] args) { 
    Outer outer = new Outer(); 
    Inner inner = outer.new Inner(); 
    System.out.println(inner); 

    outer = null; 
    inner = outer.new Inner(); // FAIL ... throws an NPE 
} 

L'output è:

outer is [email protected] 
Exception in thread "main" java.lang.NullPointerException 
     at Outer.main(Outer.java:19) 

dimostrando che il nostro tentativo di creare un Inner con un riferimento null al suo Outer non riuscito.

Infatti, se ci si infila nella busta "Pure Java" non si può rompere questo.

Tuttavia, ogni Inner istanza ha un nascosto final campo sintetico (chiamato "this$0") che contiene il riferimento al Outer. Se sei davvero ingannevole, è possibile utilizzare "non puro" per assegnare null al campo.

  • È possibile utilizzare Unsafe per farlo.
  • È possibile utilizzare il codice nativo (ad es. JNI) per farlo.
  • Si potrebbe fare usando la riflessione.

In entrambi i casi lo si fa, il risultato finale è che l'espressione Outer.this valuterà a null .

In breve, è possibile un qualificato this essere null. Ma è impossibile se il tuo programma segue le regole "Pure Java".


1 - lo sconto trucchi come "scrivere" i bytecode a mano e spacciandoli come reale Java, tweaking bytecode utilizzando BCEL o simili, o saltellando in codice nativo e manipolati con i registri salvati. IMO, NON è Java. Ipoteticamente, tali cose potrebbero anche accadere come risultato di un bug JVM ... ma non ricordo tutte le segnalazioni di bug di visualizzazione.

2 - In realtà, il JLS non dice quale sarà il comportamento e potrebbe dipendere dall'implementazione ... tra l'altro.

Problemi correlati