博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
kotlin Cloneable 的奇怪行为
阅读量:4567 次
发布时间:2019-06-08

本文共 2457 字,大约阅读时间需要 8 分钟。

kotlin Cloneable 的奇怪行为

在使用 kotlin 的 Cloneable 时,发现它表示得很奇怪。如果类直接继承了 Cloneable ,那么它的表现很正常

和 java 的使用差不多,如下:

package demointerface Foo {    fun createClone(): Foo    fun doSomething()}class Bar: Foo, Cloneable {    override fun createClone(): Bar {        return this.clone() as Bar    }    override fun doSomething() {        println("Hello, world!")    }}fun main(args:Array
) { val bar = Bar() bar.doSomething() val barCloned = bar.createClone() barCloned.doSomething()}

这部分代码运行是正常的,但是如果接口 Foo 也继承了 Cloneable ,那么结果就变得很奇怪,代码如下:

package demointerface Foo: Cloneable {    fun createClone(): Foo    fun doSomething()}class Bar: Foo, Cloneable {    override fun createClone(): Bar {        return this.clone() as Bar    }    override fun doSomething() {        println("Hello, world!")    }}fun main(args:Array
) { val bar = Bar() bar.doSomething() val barCloned = bar.createClone() barCloned.doSomething()}

在调用 bar.createClone() 时,会出现异常:

Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/Cloneable$DefaultImpls    at demo.Foo$DefaultImpls.clone(demo.kt)    at demo.Bar.clone(demo.kt:8)    at demo.Bar.createClone(demo.kt:10)    at demo.DemoKt.main(demo.kt:22)Caused by: java.lang.ClassNotFoundException: java.lang.Cloneable$DefaultImpls    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)    ... 4 more

很奇怪,于是使用 jclasslib 分析了生成的 class 文件,发现了很有意思的情况:

  1. Bar 直接继承 Cloneable

    此时,Bar 的 clone 方法为:

    0 aload_0 1 invokespecial #47 
    4 areturn

    这时直接调用了 java Object 的 clone 方法

  2. Foo 继承了 Cloneable 时

    此时,Bar 的 clone 方法为:

    0 aload_0 1 invokestatic #51 
    4 areturn

    嗯,这里调用的是 Foo 接口默认实现类,java 8 的接口默认实现,好像也没有毛病,继续看看 Foo$DefaultImpls.clone

    0 aload_0 1 checkcast #9 
    4 invokestatic #14
    7 areturn

    好像有点不对了,Cloneable 是很古老的接口了,没有默认实现,jclasslib 也没有找到 Cloneable$DefaultImpls 类。

现在问题找到了, Foo 接口里面继承了 Cloneable ,而 Bar 实现 Foo 接口时,kotlin 编译后的 class 文件都会出现调用 Cloneable$DefaultImpls 的情况,kotlin 在处理接口的默认实现上有问题。

此问题已报告到 jetbrains 的 kotlin 社区,优先级为 Major ,见

按照 effiective java 的说法,java 的 Cloneable 是个很奇怪的接口,与普通的接口的行为不一样,它使用了超过语言机制本身的约定,用于标示对象的调用 clone() 时的行为。

一般情况下,最好避免使用 clone() ,可考虑使用拷贝构造函数的方式来实现类似的功能。

转载于:https://www.cnblogs.com/fengyc/p/8978219.html

你可能感兴趣的文章
字符串操作
查看>>
Visual Studio中改变environment 的布局和显示风格
查看>>
2016-XCTF Final-Richman
查看>>
文件下载
查看>>
extjs grid renderer用法
查看>>
vue 如何在循环中绑定v-model
查看>>
shell脚本
查看>>
[代码笔记]JS保持函数单一职责,灵活组合
查看>>
cmd 重定向
查看>>
【IOS开发】如何画1像素的线
查看>>
KMP模板
查看>>
luogu 1314 聪明的质检员
查看>>
[转载]求职者防骗必读!楼主亲身经历告诉你岗前培训多么不靠谱而且违法!
查看>>
Hibernate内存溢出分析一例
查看>>
基于Axis1.4的webservice接口开发(接口调用)
查看>>
Hive内置函数详解
查看>>
【转】MyEclipse快捷键大全
查看>>
IT职业技能图谱10--Hadoop家族技能图谱
查看>>
Java - 反射(1)
查看>>
控制台中显示执行的Sql语句
查看>>