简体   繁体   English

在Android Java / Kotlin中,实现接口确实可以直接访问嵌套类的局部变量

[英]In Android Java/Kotlin, does implementing an interface give it direct access to the nesting class's local variables

In Android Java/Kotlin, does implementing an interface give it direct access to the nesting class's local variables. 在Android Java / Kotlin中,实现接口确实可以直接访问嵌套类的局部变量。 More specifically, when accessing the nesting class's local variables are they passed by value or reference to the interface. 更具体地说,当访问嵌套类的局部变量时,它们是通过值或引用传递给接口的。

It's unclear to me whether you mean "fields in the outer class" or "locals in the enclosing method", but tl;dr is "everything is by reference". 我不清楚您是指“外部类中的字段”还是“包含方法中的局部对象”,但是tl; dr是“所有内容都通过引用”。 (Well, obviously primitives aren't by reference, but everything else.) (嗯,很明显,原始不是引用,而是其他所有。)


A local inner class holds a reference to the outer class. 本地内部类持有对外部类的引用。 For example, 例如,

// 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()

The Outer$Inner class has a compiler-generated final field named this$0 (which the compiler also generates code for filling in at construction time) which is what Outer.this / this@Outer actually refers to. Outer$Inner类具有一个由编译器生成的最终字段,其名称为this$0 (编译器还将在构建时生成该字段以供填充),这是Outer.this / this@Outer实际引用的。

Accessing fields in the outer class, for example 例如,访问外部类中的字段

// 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()

is translated to go through the reference to the outer, eg Outer.this.string / this@Outer.string . 转换为对外部的引用,例如Outer.this.string / this@Outer.string Ditto with method calls on the outer. 同上方法调用在外部。


An anonymous inner class has the same features as a local inner class for referencing the outer class, plus also having access to local variables in the scope where they were created. 匿名内部类具有与引用内部类的本地内部类相同的功能,并且还可以访问在创建它们的作用域中的本地变量。

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

For references to final local variables, the Java compiler generates a final field to hold them and fills them in during construction of the inner class. 为了引用final局部变量,Java编译器生成一个final字段来保存它们,并在构造内部类期间将其填充。 References to non- final local variables are not allowed in Java. Java中不允许引用非final局部变量。

Kotlin does that for val (eg final) variables, and additionally allows referencing var (eg non-final) variables. Kotlin对val (例如最终)变量执行此操作,并且还允许引用var (例如非最终)变量。

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

If a var variable is ever used by an anonymous inner class, the Kotlin compiler converts every access of it to go through a kotlin.jvm.internal.Ref wrapper. 如果匿名内部类曾经使用过var变量,则Kotlin编译器会将其每次访问都转换为通过kotlin.jvm.internal.Ref包装器进行。 A reference to this wrapper can be passed around just like a reference to final variables. 可以像对最终变量的引用一样传递对该包装的引用。 If you use the Kotlin plugin in IntelliJ IDEA or Android Studio, the IDE will underline the variable name to indicate that this wrapping is happening automatically. 如果您在IntelliJ IDEA或Android Studio中使用Kotlin插件,则IDE将在变量名称下划线,以指示这种包装是自动进行的。


None of the above was Android-specific, it is Java and Kotlin (JVM) behavior. 以上都不是特定于Android的,而是Java和Kotlin(JVM)行为。 (Kotlin JS and Kotlin native have different implementations but the observable behavior is still the same.) (Kotlin JS和Kotlin本机具有不同的实现,但是可观察到的行为仍然相同。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM