Normalny this
nigdy nie może być null
w prawdziwym kodzie Java 1 , a Twój przykład używa normalnego this
. Zobacz inne odpowiedzi, aby uzyskać więcej informacji.
Kwalifikowany nigdy nie this
powinien być null
, ale można to przełamać. Rozważ następujące:
public class Outer {
public Outer() {}
public class Inner {
public Inner() {}
public String toString() {
return "outer is " + Outer.this; // Qualified this!!
}
}
}
Kiedy chcemy utworzyć instancję Inner
, musimy to zrobić:
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
}
Wynik to:
outer is Outer@2a139a55
Exception in thread "main" java.lang.NullPointerException
at Outer.main(Outer.java:19)
pokazując, że nasza próba stworzenia Inner
z null
odniesieniem do ich Outer
zawiódł.
W rzeczywistości, jeśli trzymasz się obwiedni „czystej Javy”, nie możesz tego złamać.
Jednak każda Inner
instancja ma ukryte final
pole syntetyczne (nazywane "this$0"
), które zawiera odwołanie doOuter
. Jeśli jesteś naprawdę podstępny, możesz użyć "nieczystych" środków, aby przypisać null
do pola.
- Możesz to
Unsafe
zrobić.
- Możesz do tego użyć kodu natywnego (np. JNI).
- Możesz to zrobić za pomocą refleksji.
Tak czy inaczej, efekt końcowy jest taki, że Outer.this
wyrażenie wyniesie null
2 .
W skrócie, jest to możliwe dla wykwalifikowanego this
być null
. Ale jest to niemożliwe, jeśli Twój program przestrzega zasad „czystej Java”.
1 - Dyskontuję sztuczki, takie jak „pisanie” kodów bajtowych ręcznie i przekazywanie ich jako prawdziwej Javy, poprawianie kodów bajtowych za pomocą BCEL lub podobnego, lub przeskakiwanie do kodu natywnego i manipulowanie zapisanymi rejestrami. IMO, czyli NIE JAVA. Hipotetycznie, takie rzeczy mogą się również zdarzyć w wyniku błędu JVM ... ale nie przypominam sobie, żeby każdy widział raporty o błędach.
2 - W rzeczywistości JLS nie mówi, jakie będzie zachowanie, i może być zależne od implementacji ... między innymi.