Kotlin 伴生对象 (Companion Object)
前言
Kotlin 相对于 Java 还是有不少新特性的,本文就来介绍一下 伴生对象(companion object)的知识点。
本文大纲
0. 伴生对象(companion object)的诞生
伴生对象(companion object)的出现是为了解决 Java 静态方法(static)的反面向对象(Anti-OOP)的问题。我们知道 Java 中,static 方法是无法声明为接口,无法被重写的。用学术性话语来说,static 方法没有面向对象的 消息传递 和 延迟绑定 特性[参考]。而为了满足 Kotlin 一切皆对象的特性,以及提升与 Java 的兼容性,提出了伴生对象来代替 static 方法。
companion object 是一个对象,在类初始化时被实例化。 伴生对象不是类的 static 方法,而是类的实例化对象,所以在其内部可以声明接口,方法也可以被重写,具备面向对象的所有特点。
1. companion 的特性
声明伴生对象的语法:
特点:
伴生对象相当于类的对象,可直接通过类名访问伴生对象的成员;
每个类最多定义一个伴生对象;
kotlin 没有 static 关键字,伴生对象是为弥补 kotlin 没有 static 修饰的静态成员的不足;
@JvmStatic 注解只能用在伴生对象里,修饰伴生对象内的属性和函数。
2. companion 的实现
在 Kotlin 中,调用 Java 的 static 方法和调用 Kotlin 的 companion object 方法是一样的:
而在 Java 中,调用 static 方法和 Kotlin 中伴生 companion object 方法,有点不同:
从 Java 的调用可以发现,companion object 的 JVM 字节码,是一个声明了一个叫 Companion 的 static 变量。
而在 Kotlin 中调用一致,其实是编译器的特殊处理结果。
来反编译一下 KotlinClass
,可以看到:
伴生对象 反编译后有如下代码:
可以看到,Companion 是一个叫 KotlinClass$Companion
的类的实例,带 $ 符号表示这个类是 KotlinClass 的内部类,名字叫 Companion,所以在KotlinClass
中直接new Companion(null)
即可。
从上面的反编译代码看,实例化 Companion 使用的是一个带 DefaultConstructorMarker 入参的构造器。
出现的场景是,若 Kotlin 编译器生成特殊构造器,就会带这个参数。上面这段代码里 Kotlin 希望能实例化 Companion 类,但又不想声明一个 public 的构造器,就声明了一个特殊的构造器。DefaultConstructorMarker 值永远为 null。
DefaultConstructorMarker 的另一个场景是:带默认参数的构造器。
版权声明: 本文为 InfoQ 作者【子不语Any】的原创文章。
原文链接:【http://xie.infoq.cn/article/400e9ca82fb80f35884e45c9a】。文章转载请联系作者。
评论