Mam program w Javie, który wygląda tak.
public class LocalScreen {
public void onMake() {
aFuncCall(LocalScreen.this, oneString, twoString);
}
}
Co to LocalScreen.thisznaczy 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.thisznaczy w aFuncCall?
Odpowiedzi:
LocalScreen.thisodnosi się do thisotaczają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.thisw naszym przykładzie nie jest zdefiniowana. Nie wiem, czy to ograniczenie jest prawdziwe dla kodu bajtowego. Może nie.
Oznacza thisinstancję LocalScreenklasy zewnętrznej .
Pisanie thisbez 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.thisumoż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.thisi thisw 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.thiszawsze wskazują zewnętrzną TĘ klasę, do której odwołuje się wartość x, ale thisjest 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.thisciągurun()musi odnosić się do załączaniaa„sthis. Czy mam rację? (W ten sposób zminimalizowany kod znajduje się w.jarplikach aplikacji OSX Kindle Previewer , po prostu próbuję zrozumieć, na co patrzę.)