kotlin中的Lateinit,lazy和singleton模式

时间:2017-11-10 23:27:22

标签: java singleton kotlin lazy-initialization kotlin-lateinit

我试图将项目的某些部分从<html> <body> <div class="myChartDiv"> <canvas id="myChart" width="600" height="400"></canvas> </div> <div id="chartLegend"></div> </body> </html> 转换为java。其中一个是单身经理班。 java类看起来像这样

kotlin

另外,我将.kt反编译回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;
  }
}

}

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

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

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

4)由于我试图将这个管理器类转换为kotlin文件的影响尽可能小(这个Manager文件应该与其余的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(); } @Jvmstatic,这样我就不必更新调用这些静态字段的其他java文件了。管理器。

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

2 个答案:

答案 0 :(得分:1)

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

有趣的是,我最近遇到了同样的问题并找到this article。虽然我第一次找到它时并不喜欢这个,但我重新访问了几次并且热情高涨,很大程度上是因为:

  • 作者去了Kotlin stdlib的代码
  • 结果是一个参数化的机制,虽然有点丑陋提供重用,这是非常引人注目的

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

  • 同步
  • 复杂初始化
  • 参数化初始化(在Android中是至关重要的,其中Context god对象是不可消除的)
  • 生成的编译代码

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

答案 1 :(得分:0)

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

使用class代替类名前面的object前缀。

例如,

object Manager {
    // your implementation
}

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

您可以查看this以获取更多参考资料。

希望它会对你有所帮助。