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