Kotlin中的object關(guān)鍵字

Kotlin中的object關(guān)鍵字

參考:Kotlin中文官網(wǎng)

kotlin中object的用法一般有兩種,對(duì)象表達(dá)式對(duì)象聲明

對(duì)象表達(dá)式

所謂表達(dá)式,就是可以賦值的語(yǔ)句。

任何時(shí)候,如果我們只需要“一個(gè)對(duì)象而已”,并不需要一個(gè)類class,那么我們可以簡(jiǎn)單地寫:

fun foo() {
    val adHoc = object {
        var x: Int = 0
        var y: Int = 0
    }
    print(adHoc.x + adHoc.y)
}

比如說(shuō)我們?cè)谀承﹫?chǎng)合需要傳入一個(gè)接口類型的對(duì)象,Java中可能會(huì)用到匿名類,Kotlin中則用object處理:

window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) { /*……*/ }

    override fun mouseEntered(e: MouseEvent) { /*……*/ }
})

可以看作是一個(gè)匿名的對(duì)象。

匿名對(duì)象只能在私有方法作用域中返回,用在公有作用域中返回的實(shí)際類型則是該類型的超類,沒(méi)有超類就是Any。在匿名對(duì)象中添加的成員將無(wú)法訪問(wèn)。

class C {
    // 私有函數(shù),所以其返回類型是匿名對(duì)象類型
    private fun foo() = object {
        val x: String = "x"
    }

    // 公有函數(shù),所以其返回類型是 Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // 沒(méi)問(wèn)題
        val x2 = publicFoo().x  // 錯(cuò)誤:未能解析的引用“x”
    }
}

對(duì)象表達(dá)式中的代碼可以訪問(wèn)來(lái)自包含它的作用域的變量。

fun countClicks(window: JComponent) {
    var clickCount = 0
    var enterCount = 0

    window.addMouseListener(object : MouseAdapter() {
        override fun mouseClicked(e: MouseEvent) {
            clickCount++
        }

        override fun mouseEntered(e: MouseEvent) {
            enterCount++
        }
    })
    // ……
}

對(duì)象聲明

和Class關(guān)鍵字一樣,用于聲明一個(gè)類,該類自動(dòng)實(shí)現(xiàn)單例模式。不能被賦值。

object Test {
    val a = 0;
}

該類字節(jié)碼文件轉(zhuǎn)成Java后如下:

public final class Test {
   private static final int a;
   @NotNull
   public static final Test INSTANCE;

   public final int getA() {
      return a;
   }

   private Test() {
   }

   static {
      Test var0 = new Test();
      INSTANCE = var0;
   }
}

訪問(wèn)的時(shí)候不用像Java一樣getInstance,可以直接Test表示這個(gè)對(duì)象。

注意:對(duì)象聲明不能在局部作用域(即直接嵌套在函數(shù)內(nèi)部),但是它們可以嵌套到其他對(duì)象聲明或非內(nèi)部類中。

伴生對(duì)象

類內(nèi)部的對(duì)象聲明可以用 companion 關(guān)鍵字標(biāo)記:

class Test {
    companion object A {
        val a = "hello"
        fun create() = "內(nèi)部類中的方法"
    }
}

這樣做的好處是可以略過(guò)該類部?jī)?nèi)名,直接訪問(wèn)到類中的對(duì)象或方法:

val a = Test.a
val b = Test.create()

這樣一來(lái)這個(gè)對(duì)象聲明的名字就不重要了,所以在Kotlin語(yǔ)法中可以直接省略。(省略后kotlin自動(dòng)將該對(duì)象聲明命名為Companion

class Test {
    companion object {

    }
}
val companion = Test.Companion

這種形式的對(duì)象聲明就叫伴生對(duì)象

通常咱們?cè)谟肒otlin的時(shí)候會(huì)用伴生對(duì)象來(lái)充當(dāng)Java中的靜態(tài)(static),但實(shí)際上它們是有區(qū)別的,用伴生對(duì)象生成的字節(jié)碼轉(zhuǎn)成Java后如下:

伴生對(duì)象 對(duì)象聲明
Kotlin寫法
Kotlin-伴生對(duì)象
Kotlin-對(duì)象聲明
轉(zhuǎn)化成Java
Java-伴生對(duì)象
Java對(duì)象聲明

當(dāng)然,在 JVM 平臺(tái),如果使用 @JvmStatic 注解,你可以將伴生對(duì)象的成員生成為真正的靜態(tài)方法和字段。更詳細(xì)信息請(qǐng)參見(jiàn)Java 互操作性一節(jié) 。

對(duì)象表達(dá)式和對(duì)象聲明之間的語(yǔ)義差異

對(duì)象表達(dá)式和對(duì)象聲明之間有一個(gè)重要的語(yǔ)義差別:

  • 對(duì)象表達(dá)式是在使用他們的地方立即執(zhí)行(及初始化)的;
  • 對(duì)象聲明是在第一次被訪問(wèn)到時(shí)延遲初始化的;
  • 伴生對(duì)象的初始化是在相應(yīng)的類被加載(解析)時(shí),與 Java 靜態(tài)初始化器的語(yǔ)義相匹配。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容