📌 思维导图:
学习任何东西,都有几个方面
- 他为什么出现
- 他的应用场景
- 他的具体用法
- 他的底层实现
- 他的设计思想
围绕这几个问题我们来详细聊聊 kotlin中的 object
让我们从object关键字是什么说起
我们觉得一个关键字嘛,记住就好,其实语言的设计者在设计的时候一定是认真考虑了的,所以我们应该站在设计者的角度来思考一些问题
object
字面翻译过来就是对象,那他的意思是我们在定义对象?感觉怪怪的,定义对象,不应该是创建对象,定义类吗?再想想 定义类的目的是为什么?不就是为了创建对象,让对象去工作,去服务。这样一来定义对象似乎也合理???。 其实 object
在表达的意思是:定义类的同时创建对象
我们来好好解读一下 定义类的同时创建对象这句话
- 最终的结果是一个对象
- 我们无法手动创建对象(底层原理就是构造器被私有化) 表达了他是一个单例 (单个对象)
所以通俗一点就是:我们定义了有且仅有一个单例对象
不过在反编译后:会发现这种单例模式是饿汉式
让我们来想想他的应用场景:什么时候我们只需要一个对象就可以了 最容易想到的就是单例,还有呢? 发散一下,什么时候我们我们只会临时用一下对象而且以后再也不会用他了,想到了吗?是否就是 匿名内部类 Java中的匿名内部类其实也是一个对象哦
所以应用场景不就出来了吗
- 单例
- 匿名内部类
但是我们的用的单例就只是一个没有参数的单例吗?好像不是吧,我们也需要有带参数的单例,这个时候就只能自己实现了。不过我们来思考一下为什么我们使用 object
关键字定义的单例不能有有参数?那是因为在我们定义好类的时候,这个对象也必须创建完成,没有时间接受外部传递的参数。
也许伴生对象只是表面功夫
说到 object
相信大家应该也熟悉 companion object
那他们之间有什么区别呢???
从名字上看就能猜到伴生对象和谁伴生呢??? 所以伴生对象一定是在内部,所以他就和外部的类伴生。既然是伴生就一定有一定的关系,那具体什么关系呢???
1//kotlin
2class DiffObject {
3 companion object Inner {
4
5 }
6}
7
8--------------------------------------------------
9//反编译Java (精简后)
10public final class DiffObject {
11 @NotNull
12 public static final DiffObject.Inner Inner =
13 new DiffObject.Inner((DefaultConstructorMarker)null);
14
15 public static final class Inner {
16 private Inner() {
17 }
18
19 // $FF: synthetic method
20 public Inner(DefaultConstructorMarker $constructor_marker) {
21 this();
22 }
23 }
24}
看到反编译后的代码我想我们能大概能猜出伴生的意思了,原来就是外部类持有一个伴生对象的引用呀。注意这个引用是static final 所以引用的对象不可变,而且伴生对象的构造器不是私有化的,就是自动生成的,我们没法调用。总结一下:伴生对象也是单例
让我们看看嵌套object是什么情况
1//kotlin
2class DiffObject {
3
4 object Inner {
5
6 }
7}
8----------------------------------------
9//java
10public final class DiffObject {
11 public static final class Inner {
12 @NotNull
13 public static final DiffObject.Inner INSTANCE;
14
15 private Inner() {
16 }
17
18 static {
19 DiffObject.Inner var0 = new DiffObject.Inner();
20 INSTANCE = var0;
21 }
22 }
23}
看的出来不同点就在于外部类没有持有object类的对象,自己的对象自己持有
那么问题就变成了,引用位置的不同,难道会有什么不同的效果???
⛳我没有想出来,看看各位大佬有没有知道的???
不过从用法上我看出了点不同
伴生对象可以不用声明名字,也能通过外部类调用,因为外部类持有伴生对象的引用,这是我猜测出来的。
从用法上:
- 嵌套object 更像是 调用静态内部类的方法
- 伴生对象更像是调用自己的静态方法。
但是两者实现的本质都是通过单例实现的类属性和类方法
番外问题:Kotlin真的没有类方法吗???
我看了 《Java编程思想》,有点小猜测,构造器不就是类方法,难道构造器需要对象调用???
当然只是我的推论
总结一下吧
- object的本质:创建类的同时创建对象
- 应用场景:匿名内部类 单例
- 通过内部类单例实现了类方法和类属性。
- 伴生对象的实现 让我们调用方认为是类的方法 而 嵌套object则是内部类的类方法和属性
问个问题:为什么嵌套类(静态内部类)单例能实现和类方法和类属性的特性???
- 答案