首页 文章

kotlin中的Lateinit,lazy和singleton模式

提问于
浏览
3

我正在尝试将项目的某些部分从 java 转换为 kotlin . 其中一个是单身经理班 . java类看起来像这样

public class Manager {
  private static volatile Manager Instance = null;
  private static final Object InstanceLock = new Object();
  private Manager(Object1 object1, Object2 object2, Object3 object3){//...};
  public static boolean isInitialized(){
    synchronized(InstanceLock){
        return Instance == null;
    }
  }
  public static void initialize(Object1 object1, Object2 object2, Object3 object3){
      if(Instance == null){
         synchronized(InstanceLock){
             if(Instance == null){Instance = new Manager(object1, object2, object3};
         }
      }
  }
  public static getInstance(){
       Precondition.checkNotNull(Instance, msg...);
       return Instance;
  }
}

另外,我将.kt反编译回java . 在伴侣类中,我得到以下代码 .

public static final class Companion {
  @Nullable
  public final Manager getInstance() {
     return Manager.instance;
  }

  private final void setInstance(Manager var1) {
     Manager.instance = var1;
  }

  private final Object getInstanceLock() {
     return Manager.InstanceLock;
  }

  public final boolean isInitialized() {
     Object var1 = Manager.Companion.getInstanceLock();
     synchronized(var1){}

     boolean var4;
     try {
        var4 = Manager.Companion.getInstance() == null;
     } finally {
        ;
     }

     return var4;
  }

  public final void initialize(@NotNull String string1, @NotNull String string2) {
     Intrinsics.checkParameterIsNotNull(string1, "string1");
     Intrinsics.checkParameterIsNotNull(string2, "string2");
     if (((Manager.Companion)this).getInstance() == null) {
        Object var3 = ((Manager.Companion)this).getInstanceLock();
        synchronized(var3){}

        try {
           if (Manager.Companion.getInstance() == null) {
              Manager.Companion.setInstance(new Manager(string1, string2, (DefaultConstructorMarker)null));
           }

           Unit var5 = Unit.INSTANCE;
        } finally {
           ;
        }
     }

  }

  private Companion() {
  }

  // $FF: synthetic method
  public Companion(DefaultConstructorMarker $constructor_marker) {
     this();
  }

}

1)如何通过在kotlin伴侣对象中使用lateinit或lazy实现线程安全,单例?我可以看到,反编译的java代码在初始化函数中有一个同步调用,但在同步体中没有任何内容 .

2)我认为kotlin object / lazy带有线程安全保证,如何在双重检查锁定模式中利用它?

3)是否有比双重检查锁定模式更好的模式?假设构造函数确实需要参数 .

4)因为我试图将这个管理器类转换为kotlin文件的影响尽可能小(这个Manager文件应该与其余的java代码一起工作),最好的方法是什么?我注意到我必须在伴随对象内的一些其他变量或函数中添加 @Jvmstatic@Jvmfield ,这样我就不必更新在manager中调用这些静态字段的其他java文件 .

5)另外一个问题,如果这位经理现在在纯kotlin环境中工作,那么实现具有多个参数的单例类的最佳实践是什么?

2 回答

  • 0

    第一个答案没有解决同步问题,顺便说一下,这仍然是一个不太重要的复杂性 . 还有很多人跑来跑去说只是做双重检查 . 但是有一些非常引人注目的论据表明DCL并不总是有效 .

    有趣的是,我最近遇到了同样的问题并找到了this article . 虽然我第一次发现它时并不喜欢这种情况,但我重复了几次并对其进行了热身,很大程度上是因为:

    • 作者去了Kotlin stdlib的代码

    • 结果是一种参数化机制,虽然有点丑陋提供重用,这是非常引人注目的

    请注意,这个问题都涉及到主要问题:

    • 同步

    • 复杂的初始化

    • 参数化初始化(在Android中至关重要,其中Context god对象是不可消除的)

    • 结果编译代码

    简而言之,我认为这是关于这个主题的第一个也是最后一个词,令人惊讶的是,在Medium上找到了 .

  • 1

    我没有回答你的所有问题,但有一种定义的方法可以在Kotlin中创建一个单例类 .

    而不是在类名前面使用 class 前缀,而是使用 object .

    例如,

    object Manager {
        // your implementation
    }
    

    这使得这个类单例,你可以直接使用它来自Java,如 Manager.getInstance() (我没有记住确切的语法,但这应该工作) . Kotlin为您创造了它 .

    您可以查看this以获取更多参考 .

    希望它会帮助你一点点 .

相关问题