Mam program w Javie, który wygląda tak.
public class LocalScreen {
public void onMake() {
aFuncCall(LocalScreen.this, oneString, twoString);
}
}
Co to LocalScreen.this
znaczy w aFuncCall
?
Mam program w Javie, który wygląda tak.
public class LocalScreen {
public void onMake() {
aFuncCall(LocalScreen.this, oneString, twoString);
}
}
Co to LocalScreen.this
znaczy w aFuncCall
?
Odpowiedzi:
LocalScreen.this
odnosi się do this
otaczającej klasy.
Ten przykład powinien to wyjaśnić:
public class LocalScreen {
public void method() {
new Runnable() {
public void run() {
// Prints "An anonymous Runnable"
System.out.println(this.toString());
// Prints "A LocalScreen object"
System.out.println(LocalScreen.this.toString());
// Won't compile! 'this' is a Runnable!
onMake(this);
// Compiles! Refers to enclosing object
onMake(LocalScreen.this);
}
public String toString() {
return "An anonymous Runnable!";
}
}.run();
}
public String toString() { return "A LocalScreen object"; }
public void onMake(LocalScreen ls) { /* ... */ }
public static void main(String[] args) {
new LocalScreen().method();
}
}
Wynik:
An anonymous Runnable!
A LocalScreen object
Ten post został przepisany jako artykuł tutaj .
a.this
w naszym przykładzie nie jest zdefiniowana. Nie wiem, czy to ograniczenie jest prawdziwe dla kodu bajtowego. Może nie.
Oznacza this
instancję LocalScreen
klasy zewnętrznej .
Pisanie this
bez kwalifikatora zwróci wystąpienie klasy wewnętrznej , w której znajduje się wywołanie.
Kompilator pobiera kod i robi z nim coś takiego:
public class LocalScreen
{
public void method()
{
new LocalScreen$1(this).run;
}
public String toString()
{
return "A LocalScreen object";
}
public void onMake(LocalScreen ls) { /* ... */ }
public static void main(String[] args)
{
new LocalScreen().method();
}
}
class LocalScreen$1
extends Runnable
{
final LocalScreen $this;
LocalScreen$1(LocalScreen $this)
{
this.$this = $this;
}
public void run()
{
// Prints "An anonymous Runnable"
System.out.println(this.toString());
// Prints "A LocalScreen object"
System.out.println($this.toString());
// Won't compile! 'this' is a Runnable!
//onMake(this);
// Compiles! Refers to enclosing object
$this.onMake($this);
}
public String toString()
{
return "An anonymous Runnable!";
}
}
Jak widać, gdy kompilator przyjmuje klasę wewnętrzną, konwertuje ją na klasę zewnętrzną (była to decyzja projektowa podjęta DŁUGO dawno temu, aby maszyny wirtualne nie musiały być zmieniane, aby zrozumieć klasy wewnętrzne).
Kiedy tworzona jest niestatyczna klasa wewnętrzna, potrzebuje odwołania do rodzica, aby mogła wywoływać metody / zmienne dostępu klasy zewnętrznej.
To, co było w klasie wewnętrznej, nie jest właściwym typem, musisz uzyskać dostęp do klasy zewnętrznej, aby uzyskać odpowiedni typ do wywołania metody onMake.
new LocalScreen$1().run;
być new LocalScreen$1(this).run;
?
Class.this
umożliwia dostęp do instancji klasy zewnętrznej. Zobacz poniższy przykład.
public class A
{
final String name;
final B b;
A(String name) {
this.name = name;
this.b = new B(name + "-b");
}
class B
{
final String name;
final C c;
B(String name) {
this.name = name;
this.c = new C(name + "-c");
}
class C
{
final String name;
final D d;
C(String name) {
this.name = name;
this.d = new D(name + "-d");
}
class D
{
final String name;
D(String name) {
this.name = name;
}
void printMe()
{
System.out.println("D: " + D.this.name); // `this` of class D
System.out.println("C: " + C.this.name); // `this` of class C
System.out.println("B: " + B.this.name); // `this` of class B
System.out.println("A: " + A.this.name); // `this` of class A
}
}
}
}
static public void main(String ... args)
{
final A a = new A("a");
a.b.c.d.printMe();
}
}
Wtedy dostaniesz.
D: a-b-c-d
C: a-b-c
B: a-b
A: a
Wiem, jakie jest twoje zdezorientowanie, właśnie teraz napotykam problem, powinna mieć specjalną scenę, aby je rozróżnić.
class THIS {
def andthen = {
new THIS {
println(THIS.this.## + ":inner-THIS.this.##")
println(this.## + ":inner-this.##")
new THIS {
println(THIS.this.## + ":inner-inner-THIS.this.##")
println(this.## + ":inner-this.##")
}
}
}
def getInfo = {
println(THIS.this.## + ":THIS.this.##")
println(this.## + ":this.##")
}
}
Możesz zobaczyć różnicę między THIS.this
i this
w nowej TEJ operacji przez hashcode (. ##)
test w konsoli scala:
scala> val x = new THIS
x: THIS = THIS@5ab9b447
scala> val y = x.andthen
1522119751:inner-THIS.this.##
404586280:inner-this.##
1522119751:inner-inner-THIS.this.##
2027227708:inner-this.##
y: THIS = THIS$$anon$1@181d7f28
scala> x.getInfo
1522119751:THIS.this.##
1522119751:this.##
THIS.this
zawsze wskazują zewnętrzną TĘ klasę, do której odwołuje się wartość x, ale this
jest poza anonimową nową operacją.
public class a { private class a { public void run() { System.out.println(a.this.toString()); } }
Przypuszczam, że to ta sama sprawa;a.this
ciągurun()
musi odnosić się do załączaniaa
„sthis
. Czy mam rację? (W ten sposób zminimalizowany kod znajduje się w.jar
plikach aplikacji OSX Kindle Previewer , po prostu próbuję zrozumieć, na co patrzę.)