写点什么

Kotlin 伴生对象 (Companion Object)

作者:子不语Any
  • 2022-11-30
    湖南
  • 本文字数:1291 字

    阅读完需:约 4 分钟

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 的特性

声明伴生对象的语法:


companion object ObjectName : [0~N个父类型] { //伴生对象类体 }// ObjectName 可省略
复制代码


特点:


  • 伴生对象相当于类的对象,可直接通过类名访问伴生对象的成员;

  • 每个类最多定义一个伴生对象;

  • kotlin 没有 static 关键字,伴生对象是为弥补 kotlin 没有 static 修饰的静态成员的不足;

  • @JvmStatic 注解只能用在伴生对象里,修饰伴生对象内的属性和函数。

2. companion 的实现

在 Kotlin 中,调用 Java 的 static 方法和调用 Kotlin 的 companion object 方法是一样的:


JavaClass.staticFun() // 调用 Java 中静态方法KotlinClass.companionFun() // 调用 Kotlin 中伴生对象的方法
复制代码


而在 Java 中,调用 static 方法和 Kotlin 中伴生 companion object 方法,有点不同:


JavaClass.staticFun(); // Java 中调用 static 方法KotlinClass.Companion.companionFun(); // 在Java中,调用伴生companion
复制代码


从 Java 的调用可以发现,companion object 的 JVM 字节码,是一个声明了一个叫 Companion 的 static 变量。


而在 Kotlin 中调用一致,其实是编译器的特殊处理结果。


来反编译一下 KotlinClass,可以看到:


// KotlinClass.classpublic final class KotlinClass {    public static final Companion companion = new Companion(null);}
复制代码


伴生对象 反编译后有如下代码:


// KotlinClass$Companion.classpublic final class KotlinClass$Companion {    private DownloadExecutor$Companion() {    }
public /* synthetic */ DownloadExecutor$Companion(DefaultConstructorMarker $constructor_marker) { this(); } public final void companionFun() { }}
复制代码


可以看到,Companion 是一个叫 KotlinClass$Companion 的类的实例,带 $ 符号表示这个类是 KotlinClass 的内部类,名字叫 Companion,所以在KotlinClass中直接new Companion(null)即可。


从上面的反编译代码看,实例化 Companion 使用的是一个带 DefaultConstructorMarker 入参的构造器。

出现的场景是,若 Kotlin 编译器生成特殊构造器,就会带这个参数。上面这段代码里 Kotlin 希望能实例化 Companion 类,但又不想声明一个 public 的构造器,就声明了一个特殊的构造器。DefaultConstructorMarker 值永远为 null。

DefaultConstructorMarker 的另一个场景是:带默认参数的构造器。

发布于: 刚刚阅读数: 3
用户头像

子不语Any

关注

If not now,when? 2022-09-17 加入

安卓攻城狮

评论

发布
暂无评论
Kotlin伴生对象(Companion Object)_android_子不语Any_InfoQ写作社区