Kotlin伴生对象及其字节码

 与Java不同的是,在kotlin中,类是没有显式的static方法和static成员变量的,都是通过伴生对象的形式间接提供的。下面来谈谈Kotlin中的伴生对象。

 1. 对象声明,object declaration,如下所示:

object MyObject {
    fun method() {
        println("MyObject method")
    }
}

fun main(args: Array) {
    MyObject.method()
}

 2. 伴生对象,companion object,

  • 在大多数情况下,kotlin推荐的做法是使用包级别的函数来作为静态方法,kotlin会将包级别的函数当作静态方法来看待;
  • 在kotlin中,一个类中只能有一个伴生对象,伴生对象的名字可以省略,如果省略(不提供伴生对象的名字),那么编译器会提供一个默认的名字Companion。如下所示:
class MyCompanion {

    companion object MyObject {

        var a:Int = 100

        @JvmStatic
        fun method() {
            println("method invoked")
        }
    }
}

fun main(args: Array) {
    MyCompanion.MyObject.method() // 演示用,实际会省略MyObject
    println("--------------")

    println(MyCompanion.a)
    MyCompanion.method() // 类似于静态方法,kotlin中没有静态方法
    println("--------------")

    println(MyCompanion.javaClass)
}

注意:

  • 虽然伴生对象的成员看起来像是Java中的静态成员,但在运行期它们依旧是真实对象的实例成员;
  • 在JVM上,可以将伴生对象的成员真正生成为类的静态方法和属性,这是通过@JvmStatic注解实现的;
  • 伴生对象在编译后会生成一个静态内部类。

 利用javap命令对伴生对象MyCompanion反编译后的结果如下:

➜  kotlin-lecture javap com.ssy.kotlin.MyCompanion
Compiled from "HelloKotlin19.kt"
public final class com.ssy.kotlin.MyCompanion {
  public static final com.ssy.kotlin.MyCompanion$MyObject MyObject;
  public com.ssy.kotlin.MyCompanion();
  static {};
  public static final int access$getA$cp();
  public static final void access$setA$cp(int);
  public static final void method();
}

通过上面的结果可以看出,加了@JvmStatic注解,会出现一个static的method()方法。
下面将@JvmStatic注解注释掉后,重新用javap进行反编译,结果如下:

➜  kotlin-lecture javap com.ssy.kotlin.MyCompanion
Compiled from "HelloKotlin19.kt"
public final class com.ssy.kotlin.MyCompanion {
  public static final com.ssy.kotlin.MyCompanion$MyObject MyObject;
  public com.ssy.kotlin.MyCompanion();
  static {};
  public static final int access$getA$cp();
  public static final void access$setA$cp(int);
}

通过上面的结果可以看出,@JvmStatic注解注释后,static的method()方法没有了。
从上面可以得出结论:伴生对象中的方法上加与不加@JvmStatic,对程序调用上(对使用者)是没有任何影响的,只是在底层的字节码形式上存在明显的差别。

好了,就先写到这里。

你可能感兴趣的:(Kotlin伴生对象及其字节码)