object關(guān)鍵字主要有三種使用場景
- 對象聲明(object declaration)
- 伴生對象(companion object)
- 對象表達(dá)式(object expression)
對象聲明(object declaration)
- 將類的聲明和定義該類的單例對象結(jié)合在一起(即通過object就實現(xiàn)了單例模式)
- 對象聲明中不能包含構(gòu)造器(包括主構(gòu)造器和次級構(gòu)造器)
Kotlin實現(xiàn)及調(diào)用
object KotlinTest {
public var a = 0;
}
fun main() {
var b = KotlinTest.a;
}
轉(zhuǎn)成Java及調(diào)用
public final class KotlinTest {
@NotNull
public static final KotlinTest INSTANCE;
private KotlinTest() {
}
static {
KotlinTest var0 = new KotlinTest();
INSTANCE = var0;
}
}
//java 調(diào)用
public JavaTest() {
int a = KotlinTest.INSTANCE.getA();
}
Kotlin 中的 object 本質(zhì)上就是 Java 中簡單的單例模式,同時它的構(gòu)造方法是 private 的,因此 object 類不能自定義構(gòu)造方法!
伴生對象(companion object)
在 Kotlin 中是沒有 static 關(guān)鍵字的!想要實現(xiàn)通過 類名.xxx() 的方式調(diào)用工具方法,可以使用上述的 object 類,但 object 本身就是一個對象,我們無法在外部調(diào)用其構(gòu)造方法,既然想擁有 object 類(通過類名調(diào)用方法)與 class 類(外部可以調(diào)用構(gòu)造方法)的兩種特性,這時伴生對象 companion object 就完全可以滿足這個需求:
Kotlin實現(xiàn)及調(diào)用
class KotlinTest {
companion object {
var a = 0;
fun test() {}
}
fun main() {
val b: Int = KotlinTest.a;
}
}
轉(zhuǎn)成Java及調(diào)用
public final class KotlinTest {
private static int a;
@NotNull
public static final KotlinTest.Companion Companion = new KotlinTest.Companion((DefaultConstructorMarker)null);
public static final class Companion {
public final int getA() {
return KotlinTest.a;
}
public final void setA(int var1) {
KotlinTest.a = var1;
}
public final void test() {
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
//java 調(diào)用
public class JavaTest {
public JavaTest() {
int a = KotlinTest.Companion.getA();
}
}
Kotlin 中的 companion object 其實對應(yīng)到 Java 中也就只是 一個靜態(tài)內(nèi)部類實例而已。當(dāng)類中成員和伴生對象中成員重名的時候,類名調(diào)用的是伴生對象中的,實例調(diào)用的是類中的。
對象表達(dá)式(object expression)
對象表達(dá)式常用來作為匿名內(nèi)部類的實現(xiàn)
// 通過對象表達(dá)式實現(xiàn)點擊事件回調(diào)
btn.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
TODO("Not yet implemented")
}
})
@JvmField、 @JvmStatic
在對象聲明和伴生對象中,java代碼調(diào)用總會跟上INSTANCE或者Companion,Kotlin 中 的伴生對象本質(zhì)上就是靜態(tài)實例,如果想像kotlin代碼那樣直接調(diào)用,需要使用kotlin自帶的注解:@JvmStatic或者@JvmField
對于對象聲明
object KotlinTest {
@JvmField
var a = 0;
}
轉(zhuǎn)換的java代碼
public final class KotlinTest {
@JvmField
public static int a;
@NotNull
public static final KotlinTest INSTANCE;
private KotlinTest() {
}
static {
KotlinTest var0 = new KotlinTest();
INSTANCE = var0;
}
}
java代碼中在KotlinTest類中增加了靜態(tài)成員屬性
對于伴生對象
class KotlinTest {
companion object {
@JvmField
public var a = 0;
@JvmStatic
fun test() {
}
}
}
轉(zhuǎn)換的java代碼
public final class KotlinTest {
@JvmField
public static int a;
@NotNull
public static final KotlinTest.Companion Companion = new KotlinTest.Companion((DefaultConstructorMarker)null);
@JvmStatic
public static final void test() {
Companion.test();
}
public static final class Companion {
@JvmStatic
public final void test() {
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
增加了對應(yīng)的 static 屬性和方法
頂層函數(shù)
fun print() {
}
class KotlinTest {
}
轉(zhuǎn)換成Java
public final class KotlinTest {
}
// KotlinTestKt.java
public final class KotlinTestKt {
public static final void print() {
}
}
在JVM中它會生成一個類,類的名字就是你的文件名加上Kt。這個文件中的所有頂層函數(shù)編譯為這個類的靜態(tài)函數(shù)。因此當(dāng)從Java中調(diào)用這個函數(shù)的時候和調(diào)用任何其他靜態(tài)函數(shù)一樣。
要修改包含kotlin頂層函數(shù)的生成的類的名稱,需要為這個文件添加@JvmName注解,將其放到文件開頭,位于包名前面
@file:JvmName("PrintUtils")
package com.utils
fun print() {
}
class KotlinTest {
}
轉(zhuǎn)換成Java
public final class KotlinTest {
}
// PrintUtils.java
package com.utils;
import kotlin.Metadata;
import kotlin.jvm.JvmName;
@JvmName(
name = "PrintUtils"
)
public final class PrintUtils {
public static final void print() {
}
}
單例
class KotlinTest {
private constructor() {
}
companion object {
val instance:KotlinTest by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
KotlinTest()
}
}
}