最近有个新项目想用Kotlin写一下,刚刚看了一些kotlin语法常识,准备着手开工。刚写个开头就遇到了问题,单例咋写。努力回忆了一下Java单例的几种写法,然后尝试做了一下对比。
1、饿汉式单例
//java实现 饿汉式单例
public class SingletonDemo {
private SingletonDemo() {
}
private SingletonDemo instance = new SingletonDemo();
public SingletonDemo getInstance() {
return instance;
}
}
//kotlin写法
object SingletonDemo {
}
发现kotlin好简洁啊,一句话?参考对象声明
而且这样声明,其内部变量及函数都等同于Java state;
查看一下kotlin的字节码文件你就会发现秘密
我们进入我们的Android Studio(我的Android Studio 3.0,如果你的编译器版本过低,请自动升级) 选择Tools工具栏,选择"Kotlin",选择“Show Kotlin Bytecode"
点击"Decompile" 根据字节码得到以下代码
//懒汉式单例
//java实现
public class SingletonDemo {
private SingletonDemo() {
}
private static SingletonDemo instance ;
public static SingletonDemo getInstance() {
if (instance == null){
instance = new SingletonDemo();
}
return instance;
}
}
//kotlin实现
class SingletonDemo private constructor() {
companion object {
private var instance: SingletonDemo? = null
get() {
if (field == null) {
field = SingletonDemo()
}
return field
}
fun get(): SingletonDemo{
//因为在伴生对象声明时,内部已有getInstance方法,所以只能取其他名字
return instance!!
}
}
}
道理和java是相通的,私有化构造方法,然后自定义其属性以供访问,只是kotlin的构造方法的语法与java略有不同,参考构造函数
3、线程安全的懒汉式
//java实现
public class SingletonDemo {
private SingletonDemo() {
}
private static SingletonDemo instance ;
public static synchronized SingletonDemo getInstance() {
if (instance == null){
instance = new SingletonDemo();
}
return instance;
}
}
//kotlin实现
class SingletonDemo private constructor() {
companion object {
private var instance: SingletonDemo? = null
get() {
if (field == null) {
field = SingletonDemo()
}
return field
}
@Synchronized
fun get(): SingletonDemo{
return instance!!
}
}
}
java用synchronized关键字修饰getInstance方法,kotlin用注解@Synchronized修饰方法,内部操作相同
4、双重校验锁式(Double Check)
//java实现
public class SingletonDemo {
private SingletonDemo() {
}
private static SingletonDemo instance;
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}
//kotlin实现
class SingletonDemo private constructor() {
companion object {
val instance: SingletonDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
SingletonDemo()
}
}
}
我们居然几行代码就实现了多行的Java代码。其中我们运用到了Kotlin的延迟属性 Lazy。
Lazy是接受一个 lambda 并返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托: 第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。