Kotlin中的object关键字
object对象
在类名前直接使用 object 关键字即可声明一个类并且自动为该类初始化一个static的实例。
object Test {
val TAG = "Test"
fun test() {}
}
在Kotlin代码中可以直接使用类名 Test 来访问其成员变量和方法,在Java代码中则可以通过 Test.INSTANCE 来访问其成员变量和方法。实际上在Java代码中访问 object 实例的方法暴露了其实现的原理,上述Kotlin代码编译成字节码后如下:
public final class Test {
public final static Lcom/ocean/star/aap/Test; INSTANCE
private final static Ljava/lang/String; TAG
private <init>()V
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
MAXSTACK = 1
MAXLOCALS = 1
public final getTAG()Ljava/lang/String;
GETSTATIC com/ocean/star/aap/Test.TAG : Ljava/lang/String;
ARETURN
MAXSTACK = 1
MAXLOCALS = 1
public final test()V
RETURN
MAXSTACK = 0
MAXLOCALS = 1
static <clinit>()V
NEW com/ocean/star/aap/Test
DUP
INVOKESPECIAL com/ocean/star/aap/Test.<init> ()V
PUTSTATIC com/ocean/star/aap/Test.INSTANCE : Lcom/ocean/star/aap/Test;
LDC "Test"
PUTSTATIC com/ocean/star/aap/Test.TAG : Ljava/lang/String;
RETURN
MAXSTACK = 2
MAXLOCALS = 0
}
可以看到 object 对象会生成一个指定类名的类,在该类中生成一个名为 INSTANCE 的static实例,并在 clinit 方法中就初始化 INSTANCE 对象。然后生成一些static的方法来访问 INSTANCE 对象中的成员变量和方法。
在Kotlin中使用object 对象也是实现单例模式的一种便捷的方式。
companion object
在一个类中可以声明多个 object 对象,但只能声明一个 companion object 对象。
class Test {
companion object CTest {
}
object Test1 {
}
object Test2 {
}
}
上述代码会在Test类中生成3个内部类,分别是Test$CTest、Test$Test1 和 Test$Test2 ,并且会为 Test 类生成一个 static 的CTest 实例。
这样在Kotlin中就可以直接通过类名Test来访问 CTest 中的成员变量和方法,就好像直接访问的是Test中的static成员。
对于 companion object 对象其类名 CTest 也可以省略掉,即:
class Test {
companion object {
}
}
在省略 companion object对象类名的情况下,会自动命名为Companion,即相当于:
class Test {
companion object Companion {
}
}
object 表达式
在Kotlin中还可以通过 object 表达式来返回一个匿名对象,使用起来就像Java中的匿名内部类。
class Test {
view.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
}
})
}
实际上编译器是生成了一个内部类 Test$1,并且该类实现了View.OnClickListener 接口,在执行到object表达式的时候则会初始化一个 Test$1 对象并返回。