Kotlin伴隨對(duì)象的初始化方法示例講解
在Java中我們知道靜態(tài)變量會(huì)在類(lèi)加載時(shí)機(jī)的“初始化”階段得到賦值(編譯器會(huì)收集類(lèi)中的靜態(tài)變量及靜態(tài)代碼塊,然后在類(lèi)構(gòu)造方法<clinit>()中執(zhí)行,注意:這里不是實(shí)例構(gòu)造方法),也就是真正運(yùn)行程序中的代碼;執(zhí)行完類(lèi)構(gòu)造方法之后才會(huì)執(zhí)行我們熟悉的實(shí)例構(gòu)造方法。
而在Kotlin中有所謂的伴隨對(duì)象,用過(guò)的同學(xué)都知道,它的功能類(lèi)似于Java中的靜態(tài)變量,那它又是什么時(shí)候初始化的呢?來(lái)看一個(gè)例子,代碼如下:
package com.zfang.testapp class KConstructTest(val first: String, val second: Int) { init {// 111 println("KConstructTest init") test(1) } companion object CC { init { // 222 println("companion object init") } fun test(index: Int) { println("test, index = $index") } } }
一個(gè)簡(jiǎn)單的kotlin類(lèi),里面包含一個(gè)伴隨對(duì)象CC,現(xiàn)在寫(xiě)一個(gè)測(cè)試類(lèi)來(lái)看一個(gè)標(biāo)記111和222這兩個(gè)地方誰(shuí)先初始化,測(cè)試代碼如下:
package com.zfang.testapp; class Test { public static void main(String[] args) { KConstructTest test = new KConstructTest("ttt", 1); KConstructTest.CC cc = test.CC; } }
一個(gè)簡(jiǎn)單的Java測(cè)試類(lèi),入口中直接new了一個(gè)KConstructTest對(duì)象,下面是程序輸出:
companion object init
KConstructTest init
test, index = 1
從輸出結(jié)果中可以看出是伴隨對(duì)象的init代碼塊先執(zhí)行了,然后才是主類(lèi)中的init代碼塊執(zhí)行。下面我們反編譯看下生存的java類(lèi)是怎樣的。結(jié)果如下:
package com.zfang.testapp; import kotlin.Metadata; import kotlin.jvm.internal.DefaultConstructorMarker; import kotlin.jvm.internal.Intrinsics; import org.jetbrains.annotations.NotNull; @Metadata( mv = {1, 7, 1}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\b\n\u0002\b\u0007\u0018\u0000 \u000b2\u00020\u0001:\u0001\u000bB\u0015\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0005¢\u0006\u0002\u0010\u0006R\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\u0007\u0010\bR\u0011\u0010\u0004\u001a\u00020\u0005¢\u0006\b\n\u0000\u001a\u0004\b\t\u0010\n¨\u0006\f"}, d2 = {"Lcom/zfang/testapp/KConstructTest;", "", "first", "", "second", "", "(Ljava/lang/String;I)V", "getFirst", "()Ljava/lang/String;", "getSecond", "()I", "CC", "app_debug"} ) public final class KConstructTest { @NotNull private final String first; private final int second; @NotNull public static final KConstructTest.CC CC = new KConstructTest.CC((DefaultConstructorMarker)null); @NotNull public final String getFirst() { return this.first; } public final int getSecond() { return this.second; } public KConstructTest(@NotNull String first, int second) {//與主構(gòu)造方法對(duì)應(yīng) Intrinsics.checkNotNullParameter(first, "first"); super(); this.first = first; this.second = second; String var3 = "KConstructTest init";//主類(lèi)中的init代碼塊 System.out.println(var3); CC.test(1); } static {//伴隨對(duì)象中的init代碼塊 String var0 = "companion object init"; System.out.println(var0); } @Metadata( mv = {1, 7, 1}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\b\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u000e\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u0006¨\u0006\u0007"}, d2 = {"Lcom/zfang/testapp/KConstructTest$CC;", "", "()V", "test", "", "index", "", "app_debug"} ) public static final class CC {//伴隨對(duì)象類(lèi) public final void test(int index) { String var2 = "test, index = " + index; System.out.println(var2); } private CC() { } // $FF: synthetic method public CC(DefaultConstructorMarker $constructor_marker) { this(); } } }
額,反編譯出來(lái)的Java代碼看上去有點(diǎn)多的樣子。不過(guò)邏輯還是很簡(jiǎn)單的,主要以下幾點(diǎn):
- 伴隨對(duì)象類(lèi)編譯成了與Java相對(duì)應(yīng)的靜態(tài)內(nèi)部類(lèi)(又叫內(nèi)嵌類(lèi)),并且伴隨對(duì)象中的init代碼塊編譯成了主類(lèi)中的靜態(tài)代碼塊。
- 主類(lèi)primary構(gòu)造函數(shù)相應(yīng)的就是Java類(lèi)的構(gòu)造函數(shù),同時(shí)主類(lèi)中的init代碼塊則編譯到了主構(gòu)造函數(shù)中了。
根據(jù)以上分析則可以得出結(jié)論:
- 伴隨對(duì)象中的init代碼塊首先執(zhí)行(因?yàn)樗痪幾g成主要的靜態(tài)代碼塊了,在類(lèi)的初始化階段就會(huì)執(zhí)行)。
- 然后才會(huì)執(zhí)行主類(lèi)中的Init代碼塊(此代碼塊被編譯到相應(yīng)Java代碼中的實(shí)例構(gòu)造方法里面了,執(zhí)行完類(lèi)構(gòu)造方法之后才會(huì)執(zhí)行實(shí)例構(gòu)造方法)。
所以如果項(xiàng)目中對(duì)主類(lèi)Init塊和伴隨對(duì)象init塊有初始化順序要求的就需要注意相應(yīng)的邏輯了。
到此這篇關(guān)于Kotlin伴隨對(duì)象的初始化方法示例講解的文章就介紹到這了,更多相關(guān)Kotlin伴隨對(duì)象的初始化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
android網(wǎng)絡(luò)圖片查看器簡(jiǎn)單實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了android網(wǎng)絡(luò)圖片查看器的簡(jiǎn)單實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Android AlertDialog多種創(chuàng)建方式案例詳解
這篇文章主要介紹了Android AlertDialog多種創(chuàng)建方式案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08Android中Viewpager禁止滑動(dòng)的實(shí)現(xiàn)
有時(shí)候在開(kāi)發(fā)中會(huì)遇到一些特別的要求,如在ViewPager中嵌入ListView,或者再嵌入一個(gè)ViewPager,那么在滑動(dòng)的時(shí)候就會(huì)造成被嵌入的XXView不能滑動(dòng)了,那么就把最外層的ViewPager禁止滑動(dòng)吧,本文就介紹了Android中Viewpager禁止滑動(dòng)的實(shí)現(xiàn)方法,需要的朋友可以參考。2017-05-05Android4.4新增函數(shù)訪問(wèn)外部存儲(chǔ)
這篇文章主要介紹了Android4.4新增函數(shù)訪問(wèn)外部存儲(chǔ)的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10Android實(shí)現(xiàn)自動(dòng)截圖腳本
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)自動(dòng)截圖腳本,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01