En Android Java / Kotlin, ¿la implementación de una interfaz le da acceso directo a las variables locales de la class de anidación?

En Android Java / Kotlin, la implementación de una interfaz le da acceso directo a las variables locales de la class de anidamiento. Más específicamente, al acceder a las variables locales de la class de anidamiento se pasan por valor o reference a la interfaz.

No me queda claro si se refiere a "campos en la class externa" o "locales en el método adjunto", pero tl; dr es "todo es por reference". (Bueno, obviamente los primitivos no son por reference, sino todo lo demás).


Una class interna local contiene una reference a la class externa. Por ejemplo,

 // Java public class Outer { public class Inner implements Supplier<Outer> { @Override public Outer get() { return Outer.this; } } } new Outer().new Inner().get(); 
 // Kotlin class Outer { inner class Inner: () -> Outer { override fun invoke() = this@Outer } } Outer().Inner().invoke() 

La class Outer$Inner tiene un campo final generado por el comstackdor llamado this$0 (que el comstackdor también genera código para rellenar en time de construcción), que es a lo que Outer.this / this@Outer realidad se refiere.

Accediendo a campos en la class externa, por ejemplo

 // Java public class Outer { String string = ""; public class Inner implements Supplier<String> { @Override public String get() { return string; } } } new Outer().new Inner().get(); 
 // Kotlin class Outer { var string: String = "" inner class Inner: () -> String { override fun invoke() = string } } Outer().Inner().invoke() 

se traduce para ir a través de la reference al exterior, por ejemplo, Outer.this.string / this@Outer.string . Ídem con el método llama al exterior.


Una class interna anónima tiene las mismas características que una class interna local para hacer reference a la class externa, además de tener acceso a las variables locales en el ámbito donde se crearon.

 // Java public class Outer { public Supplier<String> inner(final String string) { return new Supplier<String>() { @Override public Outer get() { return string; } } } } new Outer().inner("").get(); 

Para las references a las variables locales final , el comstackdor de Java genera un campo final para mantenerlas y las rellena durante la construcción de la class interna. Las references a variables locales no final no están permitidas en Java.

Kotlin hace eso para variables val (por ej., Finales), y adicionalmente permite hacer reference a variables var (por ejemplo, no finales).

 // Kotlin class Outer { fun inner(string: String): () -> String { var string2 = string return { string2 } } } Outer().inner("").invoke() 

Si una class interna anónima alguna vez usa una variable var , el comstackdor de Kotlin convierte cada acceso para pasar a través de un contenedor kotlin.jvm.internal.Ref . Una reference a este contenedor se puede pasar como una reference a las variables finales. Si utiliza el complemento de Kotlin en IntelliJ IDEA o Android Studio, el IDE subrayará el nombre de la variable para indicar que este ajuste está sucediendo automáticamente.


Ninguno de los anteriores era específico de Android, es el comportamiento de Java y Kotlin (JVM). (Kotlin JS y Kotlin native tienen implementaciones diferentes, pero el comportamiento observable sigue siendo el mismo).

  • Cómo poner un elemento en un map y devolver el map
  • Jacoco con gradle y kotlin no está creando el file jacoco.exec
  • Kotlin: posiblemente informando incorrectamente un código no utilizado
  • Setter for field se elimina por tipo de proyección
  • Kotlin se establece en nulo si no es nulo
  • Agregar vista personalizada a includedView
  • No hay salida de file kotlin.js por kotlinc-js
  • Verificar si la function está vacía en Kotlin
  • ¿Cómo llamar a una function después de la demora en Kotlin?
  • Prueba de integración de spring - No se inyectó AuthenticationPrincipal
  • esta reference en un inicializador perezoso de la propiedad de extensión kotlin