Kotlin 调用Java写的方法,参数Class<T> 神坑

看调用问题

先来看几段代码

  1. Java 写的 loadResource 方法,参数需要传入 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 写的 Parse 实现
class EmoticonMMPConfigParser : CCMMPParse<Boolean> {

    override fun parse(model: BaseAssembledResourceModel?): Boolean {
        return false
    }
}
  1. kotlin 尝试调用 Java 写的 loadResource 方法
val result = CCMMPManager.loadResource("true", EmoticonMMPConfigParser(), Boolean::class.java)

此时大家,大胆的猜测一下 result 运行结果是什么?

 result = null 

是的你没看错,运行结果并不是我们 Parse 里面返回的 false,而是返回了 null。 为什么啊???

单独跟踪一下,会发现问题出在这里:

if (clazz.isInstance(result)){
    //这里在判断类型的时候,出错了的,并没有走到这个case中
            return clazz.cast(result);
        }   
//走到这里了的,所以返回 null
        return  null;

那问题来了的,为什么 clazz.isInstance(result) 判断的结果是 false 呢,我们调用的是时候明明传入的Class<T>是Kotlin的 Boolean::class.java, 解析的 parse 也是用 Kotlin 写的方法,返回的也是 Boolean啊, 输入输出的应该是同一个类型,为什么判断结果却是告诉我们不是一个类型呢???

一开始怀疑是,kotlin 和 Java 相互调用的时候,之间发生了什么未知的坑,好那么试试纯用kotlin 写一代吗验证一下。

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

    }

    fun getB():Boolean {
        return true
    }

你猜结果如何???

isInstance: false

Why ???

先说如何解决这个问题: 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)}")

你猜结果如何???

isInstance: false
isInstance: true

parse 也换换?

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

result 运行结果是什么?

 result = false 

Good.

好,现在来分析一下,问题到底出在哪里?

首先来罗列一下代码

Boolean::class.java 指向的是 kotlin 标准库里面定义的Boolean.kt类:

Boolean.kt

Boolean::class.javaObjectType 指向的是 kotlin 标准库中 JvmClassMappingKt 中的一个方法:

javaObjectType

返回的是JavaLangBoolean::class.java, 即JDK中的 Boolean.java 类:

Boolean.java

而我们用 kotlin 写的parse,在运行时返回的 false是JVM给我们的基本类型(你可以理解是拆箱之后的数值),也就是对应的是 JavaLangBoolean::class.java, 而非我们以为的kotlin中写的 Boolean.kt

延伸 '编译阶段的语法糖' 拆箱和装箱

类似的其他的kotlin基本类型,也有这样的问题:
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.

写在最后

我对JVM,其实没有研究过,虽然以前上学的时候学过的,但可惜的是早就忘在脑后了的,所以如果哪里写的不对的,请见谅并希望指出来告诉我。

写这篇文章,只是为了记录这个神坑。并且加深了之前自己的理解(也许是错误的),一切基于JVM的语言,最终都逃不过JVM的规范,换言之,你也可以创造一门新的JVM语言。

也是我在之前写过一篇文章中提到的《一张图,三分钟,掌握 Swift & Kotlin》

聊到这里,不知道大家有没有同样的感受。我们的圈子里面有两个关键字:
语言: 到目前为止,有那么多语言,每个语言都在不同平台上展示着自己的优势。
工程师: 擅长不同的语言,在不同平台上去编码。
所以,楼主坚信语言仅仅是工程师的一把工具而已,用来在不同的平台上砍瓜切菜。楼主个人认为,你我都有学不完的语言,也很难做到拍着胸脯说自己完全掌握了什么什么语言,但作为拿工具的我们,可以做到的是,掌握拿工具的姿势,在不同平台环境下只是选择更加合适的工具,去拿刀(Swift)还是拿斧头(Kotlin)而已。语言是用来驾驭的,千万不要被语言牵着鼻子走。(所以前言里面说的 这篇文章适合已经学过其中一门语言,不仅仅局限与Swift & Kotlin)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容