android - Kotlin 从工厂方法返回相同的对象

标签 android kotlin

我正在玩 Kotlin 并发现了有趣的行为。 所以假设我想要某种工厂:

internal interface SomeStupidInterface {
    companion object FACTORY {
       fun createNew(): ChangeListener {
            val time = System.currentTimeMillis()
            return ChangeListener { element -> Log.e("J2KO", "time " + time) }
        }

        fun createTheSame(): ChangeListener {
            return ChangeListener { element -> Log.e("J2KO", "time " + System.currentTimeMillis()) }
        }
    }

    fun notifyChanged()
}

java文件中定义的ChangeListener:

interface ChangeListener {
    void notifyChange(Object element);
}

然后我尝试像这样从 Java 中使用它:

ChangeListener a = SomeStupidInterface.FACTORY.createNew();
ChangeListener b = SomeStupidInterface.FACTORY.createNew();
ChangeListener c = SomeStupidInterface.FACTORY.createTheSame();
ChangeListener d = SomeStupidInterface.FACTORY.createTheSame();
Log.e("J2KO", "createNew a == b -> " + (a == b));
Log.e("J2KO", "createTheSame c == d -> " + (c == d));

结果是:

createNew: a == b -> false
createTheSame: c == d -> true

我能理解为什么 createNew 会因为关闭而返回新的对象。 但为什么我从 createTheSame 方法接收到相同的实例?

附言我知道上面的代码不是惯用的:)

最佳答案

这与性能有关。创建更少的对象显然对性能更好,所以这就是 Kotlin 试图做的事情。

对于每个 lambda,Kotlin 生成一个实现适当接口(interface)的类。因此,例如以下 Kotlin 代码:

fun create() : () -> Unit {
  return { println("Hello, World!") }
}

对应于类似的东西:

Function0 create() {
  return create$1.INSTANCE;
}

final class create$1 implements Function0 {

  static final create$1 INSTANCE = new create$1();

  void invoke() {
    System.out.println("Hello, World!");
  }
} 

您可以在此处看到始终返回相同的实例。


但是,如果您引用了 lamdba 范围之外的变量,这将不起作用:单例实例无法访问该变量。

fun create(text: String) : () -> Unit {
  return { println(text) }
}

相反,对于 create 的每次调用,都需要实例化该类的一个新实例,它可以访问 text 变量:

Function0 create(String text) {
  return new create$1(text);
}

final class create$1 implements Function0 {

  final String text;

  create$1(String text) {
    this.text = text;
  }

  void invoke() {
    System.out.println(text);
  }
} 

这就是为什么您的 ab 实例相同,但 cd 不同的原因。

关于android - Kotlin 从工厂方法返回相同的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44291217/

相关文章:

android - FragmentActivity Junit 测试

Android - 添加主屏幕快捷方式

Android Dex - 添加 jackson 库后出错

java - 如何将密封的 Kotlin 类转换为 Java 类

java - Kotlin 代码如何在 Android 应用程序中执行,它与 Java 有何不同?

Kotlin 构建器与构造器

Android,意外的按钮左右填充

android - procrank 和 dumpsys meminfo 有什么区别?

android - 手动设置Firebase Firestore缓存

gradle - 尝试将木材添加到Kotlin项目中会导致多个 'Unable to resolve dependency for…' Gradle错误