与Java不同的是,在kotlin中,类是没有显式的static方法和static成员变量的,都是通过伴生对象的形式间接提供的。下面来谈谈Kotlin中的伴生对象。
1. 对象声明,object declaration,如下所示:
object MyObject {
fun method() {
println("MyObject method")
}
}
fun main(args: Array<String>) {
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<String>) {
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,对程序调用上(对使用者)是没有任何影响的,只是在底层的字节码形式上存在明显的差别。
好了,就先写到这里。