Kotlin 調(diào)用Java寫(xiě)的方法,參數(shù)Class<T> 神坑

看調(diào)用問(wèn)題

先來(lái)看幾段代碼

  1. Java 寫(xiě)的 loadResource 方法,參數(shù)需要傳入 Class<T>
    public <T> T loadResource(String resource, CCMMPParse<T> parse, Class<T> clazz){
        HJKitConfigAssembledResourceModel model =  new HJKitConfigAssembledResourceModel();
        model.setContent(resource);
        T result = parse.parse(model);
        if (clazz.isInstance(result)){
            return clazz.cast(result);
        }   
        return  null;
    }
  1. Kotlin 寫(xiě)的 Parse 實(shí)現(xiàn)
class EmoticonMMPConfigParser : CCMMPParse<Boolean> {

    override fun parse(model: BaseAssembledResourceModel?): Boolean {
        return false
    }
}
  1. kotlin 嘗試調(diào)用 Java 寫(xiě)的 loadResource 方法
val result = CCMMPManager.loadResource("true", EmoticonMMPConfigParser(), Boolean::class.java)

此時(shí)大家,大膽的猜測(cè)一下 result 運(yùn)行結(jié)果是什么?

 result = null 

是的你沒(méi)看錯(cuò),運(yùn)行結(jié)果并不是我們 Parse 里面返回的 false,而是返回了 null。 為什么啊???

單獨(dú)跟蹤一下,會(huì)發(fā)現(xiàn)問(wèn)題出在這里:

if (clazz.isInstance(result)){
    //這里在判斷類(lèi)型的時(shí)候,出錯(cuò)了的,并沒(méi)有走到這個(gè)case中
            return clazz.cast(result);
        }   
//走到這里了的,所以返回 null
        return  null;

那問(wèn)題來(lái)了的,為什么 clazz.isInstance(result) 判斷的結(jié)果是 false 呢,我們調(diào)用的是時(shí)候明明傳入的Class<T>是Kotlin的 Boolean::class.java, 解析的 parse 也是用 Kotlin 寫(xiě)的方法,返回的也是 Boolean啊, 輸入輸出的應(yīng)該是同一個(gè)類(lèi)型,為什么判斷結(jié)果卻是告訴我們不是一個(gè)類(lèi)型呢???

一開(kāi)始懷疑是,kotlin 和 Java 相互調(diào)用的時(shí)候,之間發(fā)生了什么未知的坑,好那么試試純用kotlin 寫(xiě)一代嗎驗(yàn)證一下。

    init {
        val b = getB()
        Log.d("tag",".isInstance: ${ Boolean::class.java.isInstance(b)}")

    }

    fun getB():Boolean {
        return true
    }

你猜結(jié)果如何???

isInstance: false

Why ???

先說(shuō)如何解決這個(gè)問(wèn)題: How to reference Boolean java class from kotlin?

即 換成 javaObjectType.isInstance() :

         Log.d("tag","isInstance: ${ Boolean::class.java.isInstance(b)}")
        Log.d("tag","isInstance: ${ Boolean::class.javaObjectType.isInstance(b)}")

你猜結(jié)果如何???

isInstance: false
isInstance: true

parse 也換換?

val result = CCMMPManager.loadResource("true", EmoticonMMPConfigParser(), Boolean::class.javaObjectType)

result 運(yùn)行結(jié)果是什么?

 result = false 

Good.

好,現(xiàn)在來(lái)分析一下,問(wèn)題到底出在哪里?

首先來(lái)羅列一下代碼

Boolean::class.java 指向的是 kotlin 標(biāo)準(zhǔn)庫(kù)里面定義的Boolean.kt類(lèi):

Boolean.kt

Boolean::class.javaObjectType 指向的是 kotlin 標(biāo)準(zhǔn)庫(kù)中 JvmClassMappingKt 中的一個(gè)方法:

javaObjectType

返回的是JavaLangBoolean::class.java, 即JDK中的 Boolean.java 類(lèi):

Boolean.java

而我們用 kotlin 寫(xiě)的parse,在運(yùn)行時(shí)返回的 false是JVM給我們的基本類(lèi)型(你可以理解是拆箱之后的數(shù)值),也就是對(duì)應(yīng)的是 JavaLangBoolean::class.java, 而非我們以為的kotlin中寫(xiě)的 Boolean.kt。

延伸 '編譯階段的語(yǔ)法糖' 拆箱和裝箱

類(lèi)似的其他的kotlin基本類(lèi)型,也有這樣的問(wèn)題:
A confusion about Int::class.java.isInstance() in Kotlin

 The issue is that Int::class refers to the primitive int type, but the value is the boxed Integer type.

A workaround is to use Integer::class instead of Int::class, as this will refer to the boxed Java type.

寫(xiě)在最后

我對(duì)JVM,其實(shí)沒(méi)有研究過(guò),雖然以前上學(xué)的時(shí)候?qū)W過(guò)的,但可惜的是早就忘在腦后了的,所以如果哪里寫(xiě)的不對(duì)的,請(qǐng)見(jiàn)諒并希望指出來(lái)告訴我。

寫(xiě)這篇文章,只是為了記錄這個(gè)神坑。并且加深了之前自己的理解(也許是錯(cuò)誤的),一切基于JVM的語(yǔ)言,最終都逃不過(guò)JVM的規(guī)范,換言之,你也可以創(chuàng)造一門(mén)新的JVM語(yǔ)言。

也是我在之前寫(xiě)過(guò)一篇文章中提到的《一張圖,三分鐘,掌握 Swift & Kotlin》

聊到這里,不知道大家有沒(méi)有同樣的感受。我們的圈子里面有兩個(gè)關(guān)鍵字:
語(yǔ)言: 到目前為止,有那么多語(yǔ)言,每個(gè)語(yǔ)言都在不同平臺(tái)上展示著自己的優(yōu)勢(shì)。
工程師: 擅長(zhǎng)不同的語(yǔ)言,在不同平臺(tái)上去編碼。
所以,樓主堅(jiān)信語(yǔ)言僅僅是工程師的一把工具而已,用來(lái)在不同的平臺(tái)上砍瓜切菜。樓主個(gè)人認(rèn)為,你我都有學(xué)不完的語(yǔ)言,也很難做到拍著胸脯說(shuō)自己完全掌握了什么什么語(yǔ)言,但作為拿工具的我們,可以做到的是,掌握拿工具的姿勢(shì),在不同平臺(tái)環(huán)境下只是選擇更加合適的工具,去拿刀(Swift)還是拿斧頭(Kotlin)而已。語(yǔ)言是用來(lái)駕馭的,千萬(wàn)不要被語(yǔ)言牽著鼻子走。(所以前言里面說(shuō)的 這篇文章適合已經(jīng)學(xué)過(guò)其中一門(mén)語(yǔ)言,不僅僅局限與Swift & Kotlin)

最后編輯于
?著作權(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)容