object关键字描述
以下定义了单例A,原理大家可以看看注释,其实也挺简单的。
object A {
fun test(){}
}
//反编译代码
public final class A {
@NotNull
public static final A INSTANCE;
public final void test() {
}
private A() {
}
static {//类加载的时候实例化对象
A var0 = new A();
INSTANCE = var0;
}
}
//调用处
A.test()
//调用处反编译,通过INSTANCE对象来访问
A.INSTANCE.test();
- 使用场景:对内存影响不大,外部不需要传入参数。
by lazy单例
利用Kotlin by lazy的特性,保证对象只初始化一次,懒加载而且是线程安全。想知道原理可以看下https://juejin.cn/post/7087846746260242468
class MyApplication : Application() {
val b by lazy { B() }
}
使用场景:对内存较敏感。
双重判断
class B private constructor(context: Context) {
companion object {
@Volatile private var instance: B? = null
@JvmStatic
fun getInstance(context: Context): B {
instance ?: synchronized(B::class.java) {//1
instance ?: {//2
instance = B(context)
}
}
return instance!!
}
}
}
- 注释1、2:如果instance为空则执行冒号后面的逻辑;
- 注释3,将instance返回,不过这里用双引用总感觉有点问题,不知道有没有更好的处理方式。写法跟Java大体类似。
使用场景:对内存较敏感,外部可以传入参数。
单例构建模板
如果多个类要定义成单例,那么以上代码就得写多次,我们可以抽象模板代码。
abstract class BaseSingleInstance<in P, out R> {//1
@Volatile
private var instatnce: R? = null//2
abstract fun create(params: P): R//3
fun getInstance(params: P): R {//4
instatnce ?: synchronized(BaseSingleInstance::class.java) {
instatnce ?: create(params).apply { instatnce = this }
}
return instatnce!!
}
}
//子类实现
class B private constructor(context: Context) {//5
companion object : BaseSingleInstance<Context, B>() {
override fun create(params: Context) = B(params)
}
}
- 注释1:定义抽象类BaseSingleInstance,给子类伴生类实现,in P 表示入参为P, out R表示返回类型为R,in out控制泛型的作用域,前者为入参使用,后者为返回使用;
- 注释2:定义instatnce,存储实例对象;
- 注释3:抽象函数,由子类负责对象的构建;
- 注释4:获取实例的方法,这个没什么好说的;
- 注释5:子类B的实现。
使用场景:多个类需要实现单例。
以上分析有不对的地方,请指出,互相学习,谢谢哦!
网友评论