05 | object关键字:你到底有多少种用法?
object:匿名内部类
- 深入了解
- 翻译
- 解释
- 总结
Kotlin中的object关键字具有三种不同的语义:匿名内部类、单例模式和伴生对象。这种设计统一了类的定义和对象的创建,使得代码更加简洁和灵活。在匿名内部类的使用中,Kotlin通过object关键字来创建接口和抽象类的实例,同时支持继承抽象类和实现多个接口,相比Java更加灵活。而在单例模式中,使用object关键字可以轻松创建单例类,省去了在Java中繁琐的实现过程。虽然这种方式存在一些局限性,如不支持懒加载和传参构造单例,但Kotlin也提供了其他方式来实现单例模式,如伴生对象。通过object关键字的三种用法,读者可以深入了解Kotlin语法的灵活性和简洁性,以及与Java的对比优势。伴生对象的实战应用包括工厂模式,通过伴生对象巧妙地实现了工厂模式,统一管理类的创建,同时可以进行统一的判断,如敏感词过滤和判断用户的名称是否合法。通过伴生对象,还可以实现更加复杂的单例设计模式。文章还介绍了Kotlin中更加全面的四种单例模式,包括懒加载委托单例模式、Double Check单例模式、抽象类模板单例和接口单例模板。这些模式的介绍和比较为读者提供了更多选择和灵活性,使得他们能够根据具体需求选择最适合的单例模式。
《朱涛 · Kotlin 编程第一课》,新⼈⾸单¥59
全部留言(22)
- 最新
- 精选
- InfoQ_0880b52232bf”由于static{}代码块当中的代码,是在类加载的时候被执行的...“ 这句话是有问题的,静态代码块不是在类加载的时候执行的,而是在类初始化时执行的。
作者回复: 很抱歉出现了这个疏漏,我会改过来。也真心感谢你指出了这个问题,你让这个课程变得更好了。
2022-01-08221 - 7PromiseBaseSingleton有一个缺点:限制了单例的构造函数只有一个参数。因此可以将p改为函数类型传入。
作者回复: 不错的思路~
2022-01-0558 - 阿康我感觉可以把P换成高级函数当做参数传入,未必每个单例的creator 内部方法都是一样的,是吧?
作者回复: 不错的思路~
2022-01-057 - A Lonely Catclass DatabaseManager private constructor() { companion object { @JvmStatic val instance by lazy { DatabaseManager() } } } 这样写也行
作者回复: 赞~
2022-01-076 - 白乾涛1、文章中说"Kotlin 还是为我们提供了伴生对象,来帮助实现静态方法和变量" --- 请问伴生对象(companion object)和静态有关系吗?我感觉只是 @JvmStatic 和静态有关系。 2、文章中说"伴生对象,是嵌套单例的一种特殊情况" --- 请问伴生对象还能叫单例吗?反编译后,他都有 public 的构造方法了,而且 static 代码块也不见了 3、文章中说"@JvmStatic修饰的方法或属性会被挪到伴生对象外部的类当中" --- 这里不应该称为【挪到】吧,因为内部类中的 foo 方法还在那里,说【拷贝】更合适 4、请问【伴生对象 + @JvmStatic】有什么意义?单纯拷贝一个成员到外部类中并没有什么意义吧?
作者回复: 首先,感谢这位同学能提出这么多有趣的见解,这里我一一回复: 第一点:站在Kotlin语法层面,“伴生对象”跟“静态”已经是语法等价了。 第二点:这也是语法层面上的推导,只是说它们语法发展上的关系。另外,伴生对象确实是单例,只是我们一般不这么用。(我提供的反编译代码中public的构造方法只有编译器才能访问,我们开发者是无法直接调用的。) 第三点:确实说【拷贝】更合适。 第四点:【伴生对象 + @JvmStatic】,它的意义在于让Java调用Kotlin的时候更友好。
2022-02-1035 - loucBaseSingleton 的提取之前,getInstance 在子类的companion object中可以加 @JvmStatic,但是提取后就无法加这个注解了,造成java代码调用不友好了,这个算个缺点吧
作者回复: 是的。
2022-04-142 - 白乾涛使用 object 定义匿名内部类的时候,可以在继承一个抽象类的同时,来实现多个接口,但是反编译后为啥语法不正确? public static final void main() { <undefinedtype> item = new A() { public void funA() { } public void funB() { } public void findMan() { } }; item.findMan(); }
作者回复: 字节码反编译成Java其实也是有损的。
2022-02-092 - 郑峰creator 是唯一一个需要实现的方法,我们可以使用 SAM 转换,最终使用 Lambda 表达式来简化它的写法。 open class BaseSingleton<in P, out T : Any>(private val creator: (P) -> T) { @Volatile private var instance: T? = null fun getInstance(param: P): T = instance ?: synchronized(this) { instance ?: creator(param).also { instance = it } } }
作者回复: 嗯,不错的思路。
2022-01-162 - 神佑小鹿companion 只是为了将 @jvmstatic 修饰的方法,挪到外面么??
作者回复: 由于companion无法单独使用,如果要对比“companion object”与“object”,那么它们之间的差异,就在于字节码上的这些变化了。
2022-04-041 - 木易杨class Utils{ @JvmStatic fun foo(){ println("foo") } } 为啥@JvmStatic不能再class中写了?只能在object中。
作者回复: 因为@JvmStatic是用来修饰静态成员的啊,你想想是不是?
2022-01-1331