从探讨Kotlin单例实现讲讲其与Java代码的互相转换

来源:互联网 发布:汉王文本王扫描仪软件 编辑:程序博客网 时间:2024/06/03 13:56

Kotlin可谓是大量的语法糖,但是简约的同时也屏蔽了不少实现细节。从Java开发进而学习Kotlin开发,有时候还是会对Kotlin真实的实现产生疑问,JetBrains也考虑到这些了。所以其提供了代码互相转换的工具,使用这些工具,能更好的探究Kotlin的实现方式与原理。
今天就以单例模式为例,介绍下代码互转工具的使用。IDEA或者Android Studio的互转工具在:
Tools->Kotlin->Show kotlin Bytecode
Tools->Kotlin->Decompile kotlin to Java


1. Kotlin单例十分简单

object MySingleton {}

是的,写完了。接下来你就会怀疑,是线程安全的吗?懒汉额汉?不用查资料,来一波反编译就可以了。


2.Tools->Kotlin->Show kotlin Bytecode

写完上面这个Kotlin类,直接使用这个工具,就会把Kotlin编译后的class字节码反编译出来了。大致如下:

// class version 50.0 (50)// access flags 0x31public final class com/tian/kotlin/idoms/MySingleton {  // access flags 0x2  private <init>()V   L0    LINENUMBER 3 L0    ALOAD 0    INVOKESPECIAL java/lang/Object.<init> ()V    ALOAD 0    CHECKCAST com/tian/kotlin/idoms/MySingleton    PUTSTATIC com/tian/kotlin/idoms/MySingleton.INSTANCE : Lcom/tian/kotlin/idoms/MySingleton;    RETURN   L1    LOCALVARIABLE this Lcom/tian/kotlin/idoms/MySingleton; L0 L1 0    MAXSTACK = 1    MAXLOCALS = 1  // access flags 0x19  public final static Lcom/tian/kotlin/idoms/MySingleton; INSTANCE  // access flags 0x8  static <clinit>()V   L0    LINENUMBER 3 L0    NEW com/tian/kotlin/idoms/MySingleton    INVOKESPECIAL com/tian/kotlin/idoms/MySingleton.<init> ()V    RETURN    MAXSTACK = 1    MAXLOCALS = 0  @Lkotlin/Metadata;(mv={1, 1, 7}, bv={1, 0, 2}, k=1, d1={"\u0000\u000c\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\u0008\u00c6\u0002\u0018\u00002\u00020\u0001B\u0007\u0008\u0002\u00a2\u0006\u0002\u0010\u0002\u00a8\u0006\u0003"}, d2={"Lcom/tian/kotlin/idoms/MySingleton;", "", "()V", "production sources for module KotlinLearn"})  // compiled from: MySingleton.kt}

好吧,有人对这种汇编色彩的代码蒙头的人了。因为真的不太好阅读。这时候,就可以使用以下这个工具了。


3.Tools->Kotlin->Decompile kotlin to Java

两种使用方式,一种方式就是在使用第2步时,Kotlin Bytecode窗口顶部有一个Decompile按键,轻松一点,通过字节码反编译的Java代码就出来了。第二种方式,就是通过Tools进,但是你会发现,这个选项可能是置灰的(不可点击状态),这其实是由于你选中的并不是class文件,这是你可以去工程构建目录(build或者out目录)下,去选择你要反编译的class文件,然后再Tools下选定Decompile kotlin to Java。上面的单例,反编译后的Java代码大致是:

public final class MySingleton {   public static final MySingleton INSTANCE;   private MySingleton() {      INSTANCE = (MySingleton)this;   }   static {      new MySingleton();   }}

这里,就能看出端倪了,利用classloder机制制保证了线程安全,但由于类装载的原因有很多种,所以不能保证其实Lazy Loading,即饿汉式