2011-04-03 13 views
92

Tengo un programa Java que se ve así.Java: Class.this

public class LocalScreen { 

    public void onMake() { 
     aFuncCall(LocalScreen.this, oneString, twoString); 
    } 
} 

Lo que hace LocalScreen.this medios en aFuncCall?

Respuesta

48

Significa la instancia this de la clase LocalScreen externa.

Escribir this sin un calificador devolverá la instancia del inner class que la llamada está dentro de.

+4

Todavía no entiendo del todo. ¿Cuál es la diferencia cuando lo código como "LocalScreen.this" en comparación con "esto"?Probé ambos y el compilador solo aceptó "LocalScreen.this". El primer parámetro de aFuncCall espera una clase Parent que es una clase padre de "Somethig". –

+3

Necesita aprender sobre las clases internas. – SLaks

+1

Tengo curiosidad acerca de esto también. ¿Puedes darnos algún detalle sobre lo que esto significa? No veo ninguna clase interna definida en el código anterior; ¿cada función de Java tiene una clase anónima asociada separada de la clase de la que es miembro? – poundifdef

141

LocalScreen.this se refiere a this de la clase adjunta.

Este ejemplo debería explicarlo:

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(); 
    } 
} 

Salida:

An anonymous Runnable! 
A LocalScreen object 

Este post ha sido reescrito como un artículo here.

+2

Thnx ... fabuloso ejemplo .... simple, nd recta 2 d point –

+0

¿Qué sucede si tiene algo como: 'public class a {private class a {public void run() {System.out.println (a.this .Encadenar()); }} 'Supongo que es la misma cuestión; el 'a.this' dentro de' run() 'debe referirse a * enclosing *' a''s 'this'. ¿Estoy en lo cierto? (Así es como el código minificado está en los archivos '.jar' de la aplicación OSX Kindle Previewer, estoy tratando de entender lo que estoy viendo) –

+0

En Java, una clase interna puede no tener el mismo nombre que cualquiera de sus clases adjuntas (JLS 8.1), por lo que 'a.this' en su ejemplo no está definido. No sé si esta restricción es verdadera para bytecode. Tal vez no. – aioobe

11

Class.this permite el acceso a la instancia de la clase externa. Vea el siguiente ejemplo.

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(); 
    } 
}

Luego obtendrá.

D: a-b-c-d 
C: a-b-c 
B: a-b 
A: a
+0

La única respuesta bien explicada hasta ahora ... Es de hecho "Class.this permite el acceso a la instancia de la clase externa" y no cosas como "Class.this permite el acceso a la clase externa es esto". Una clase no tiene ningún "esto", solo las instancias tienen para referirse a sí mismas ... –

13

El compilador toma el código y hace algo como esto con ella:

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!"; 
    } 
} 

Como se puede ver, cuando el compilador toma una clase interna se convierte en una clase externa (esto era una la decisión de diseño se tomó hace mucho tiempo, por lo que no era necesario cambiar las máquinas virtuales para comprender las clases internas).

Cuando se crea una clase interna no estática necesita una referencia a la matriz para que pueda invocar métodos/variables de acceso de la clase externa.

Esto dentro de lo que era la clase interna no es del tipo apropiado, necesita obtener acceso a la clase externa para obtener el tipo correcto para llamar al método onMake.

+0

no debería 'nueva LocalScreen $ 1(). Ejecutar;' ser 'nueva LocalScreen $ 1 (esto) .run;'? – Diskutant

+0

Reparado. ¡¡Gracias!! – TofuBeer

+0

Esta es una respuesta infravalorada a la pregunta. Cosas interesantes. – BrettG

-2

Sé cuál es tu confusión. Tengo el problema justo ahora, debería tener una escena especial para distinguirlos.

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.##") 
    } 
} 

Se puede ver el diff entre THIS.this y this de nuevo esta operación mediante código hash

prueba en la consola de Scala (##.):

scala> val x = new THIS 
x: THIS = [email protected] 

scala> val y = x.andthen 
1522119751:inner-THIS.this.## 
404586280:inner-this.## 
1522119751:inner-inner-THIS.this.## 
2027227708:inner-this.## 
y: THIS = [email protected] 

scala> x.getInfo 
1522119751:THIS.this.## 
1522119751:this.## 

THIS.this siempre apuntan a esta clase externa que es referido por val x, pero this va más allá para una nueva operación anónima.