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).

  • Prueba Robolectric y LiveData
  • Escalar una vista de niño toma la misma altura
  • ¿Por qué Kotlin usa la palabra "val" para representar constante?
  • ¿Cómo pasar el token JWT de una actividad a otra?
  • ¿Cómo se usan las classs anónimas de Kotlin como arguments para las funciones nativas de JavaScript?
  • El depurador Java seleccionado actualmente no admite puntos de interrupción de tipo 'Kotlin Line Breakpoints'
  • La variable de vista de Kotlin es inesperadamente nula en el método Activity onCreate
  • ¿Cómo crear un button en Kotlin que abre una nueva actividad (Android Studio)?
  • No se pudieron encontrar las classs de Kotlin en el module de características de otro module
  • Tipo de function de Kotlin en su lugar interfaz funcional lambda
  • ¿Cómo puedo fusionar una sola <Lista <Lista <T >>> en una Lista <T> con RxJava 2?