Un normale this
non può mai essere null
nel codice Java reale 1 e il tuo esempio utilizza un normale this
. Vedi altre le altre risposte per maggiori dettagli.
Un qualificato non this
dovrebbe mai esserlo null
, ma è possibile rompere questo. Considera quanto segue:
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
, dobbiamo 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 Outer@2a139a55
Exception in thread "main" java.lang.NullPointerException
at Outer.main(Outer.java:19)
dimostrando che il nostro tentativo di creare un Inner
con un null
riferimento al suo Outer
è fallito.
In effetti, se rimani nella busta "Pure Java" non puoi romperla.
Tuttavia, ogni Inner
istanza ha un final
campo sintetico nascosto (chiamato "this$0"
) che contiene il riferimento a Outer
. Se sei veramente astuto, puoi usare mezzi "non puri" da assegnare null
al campo.
- Potresti usarlo
Unsafe
per farlo.
- È possibile utilizzare codice nativo (ad esempio JNI) per farlo.
- Puoi farlo usando la riflessione.
In ogni caso, il risultato finale è che l' Outer.this
espressione restituirà null
2 .
Insomma, per un qualificato è possibilethis
esserlo null
. Ma è impossibile se il tuo programma segue le regole "Pure Java".
1 - Sconto trucchi come "scrivere" i bytecode a mano e spacciarli per Java reale, modificare i bytecode usando BCEL o simili, o saltare nel codice nativo e scherzare con i registri salvati. IMO, questo NON è Java. Ipoteticamente, cose del genere potrebbero anche accadere a seguito di un bug di JVM ... ma non ricordo tutte le segnalazioni di bug viste.
2 - In realtà, il JLS non dice quale sarà il comportamento e potrebbe dipendere dall'implementazione ... tra le altre cose.