Kotlin 下的 5 种单例模式,一招教你看懂 Netty
学习了 Kotlin 的小伙伴肯定知道,在 Kotlin 中类没有静态方法。如果你需要写一个可以无需用一个类的实例来调用,但需要访问类内部的函数(例如,工厂方法,单例等),你可以把该类声明为一个对象。该对象与其他语言的静态成员是类似的。如果你想了解 Kotlin 对象声明的更多内容。请点击- - - 传送门
到这里,如果还是有很多小伙伴不是很相信一行代码就能解决这个功能,我们可以通过一下方式查看 Kotlin 的字节码。
查看 Kotlin 对应字节码
我们进入我们的 Android Studio(我的 Android Studio 3.0,如果你的编译器版本过低,请自动升级) 选择 Tools 工具栏,选择"Kotlin",选择“Show Kotlin Bytecode"
选择过后就会进入到下方界面:
点击"Decompile" 根据字节码得到以下代码
public final class SingletonDemo {public static final SingletonDemo INSTANCE;private SingletonDemo(){}static {SingletonDemo var0 = new SingletonDemo();INSTANCE = var0;}}
通过以上代码,我们了解事实就是这个样子的,使用 Kotlin"object"进行对象声明与我们的饿汉式单例的代码是相同的。
二、懒汉式
//Java 实现 public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static SingletonDemo getInstance(){if(instance==null){instance=new SingletonDemo();}return instance;}}//Kotlin 实现 class SingletonDemo private constructor() {companion object {private var instance: SingletonDemo? = nullget() {if (field == null) {field = SingletonDemo()}return field}fun get(): SingletonDemo{//细心的小伙伴肯定发现了,这里不用 getInstance 作为为方法名,是因为在伴生对象声明时,内部已有 getInstance 方法,所以只能取其他名字 return instance!!}}}
上述代码中,我们可以发现在 Kotlin 实现中,我们让其主构造函数私有化并自定义了其属性访问器,其余内容大同小异。
三、线程安全的懒汉式
//Java 实现 public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static synchronized SingletonDemo getInstance(){//使用同步锁 if(instance==null){instance=new Singlet
onDemo();}return instance;}}//Kotlin 实现 class SingletonDemo private constructor() {companion object {private var instance: SingletonDemo? = nullget() {if (field == null) {field = SingletonDemo()}return field}@Synchronizedfun get(): SingletonDemo{return instance!!}}
}
大家都知道在使用懒汉式会出现线程安全的问题,需要使用使用同步锁,在 Kotlin 中,如果你需要将方法声明为同步,需要添加**@Synchronized**注解。
四、双重校验锁式(Double Check)
//Java 实现 public class SingletonDemo {private volatile static SingletonDemo instance;private SingletonDemo(){}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() 只是返回记录的结果。
这里还有有两个额外的知识点。
如果你了解以上知识点,我们直接来看 Lazy 的内部实现。
Lazy 内部实现
public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =when (mode) {LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)}
观察上述代码,因为我们传入的 mode = LazyThreadSafetyMode.SYNCHRONIZED, 那么会直接走 SynchronizedLazyImpl,我们继续观察 SynchronizedLazyImpl。
Lazy 接口
SynchronizedLazyImpl 实现了 Lazy 接口,Lazy 具体接口如下:
public interface Lazy<out T> {//当前实例化对象,一旦实例化后,该对象不会再改变 public val value: T//返回 true 表示,已经延迟实例化过了,false 表示,没有被实例化,//一旦方法返回 true,该方法会一直返回 true,且不会再继续实例化 public fun isInitialized(): Boolean}
继续查看 SynchronizedLazyImpl,具体实现如下:
SynchronizedLazyImpl 内部实现
private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {private var initializer: (() -> T)? = initializer@Volatile private var _value: Any? = UNINITIALIZED_VALUE// final field is required to enable safe publication of constructed instanceprivate val lock = lock ?: this
override val value: Tget() {val _v1 = _value
评论