KotlinのisはJavaのinstanceofだよ
各位
お疲れ様です。 表題の通りKotlinのisはJavaのinstanceofを内部的には使用しています。
以上よろしくお願いいたします。
というわけで、Kotlinのパターンマッチにつかうis
が内部的にどのような処理を行っているのかが気になったので調べてみました。
方法としてはKotlinでis
を使ったコードをコンパイルしてできたクラスファイルを
Javaデコンパイラでデコンパイルします。
Kotlinのコンパイラのバージョンは'1.3.11 デコンパイラにはCFR v0.139を使用しました。
Kotlinのコード
class A(){ val a="aaa" } fun test(hoge:Int){ val b= if(hoge==0)A()else null if(b is A){ print("a") }else{ print("b") } }
これをコンパイルして得たTestKt.class
をデコンパイルした結果が以下のとおりです。
コマンド
java -jar cfr-0.139.jar out/production/classes/TestKt.class
/* * Decompiled with CFR 0.139. * * Could not load the following classes: * kotlin.Metadata */ import java.io.PrintStream; import kotlin.Metadata; @Metadata([省略]) public final class TestKt { public static final void test(int hoge) { A b; A a = b = hoge == 0 ? new A() : null; if (b instanceof A) { String string = "a"; System.out.print((Object)string); } else { String string = "b"; System.out.print((Object)string); } } }
みごとにinstanceofが登場していることがわかりますね。 Javaではinstanceofを使うのはあまり良くないとされていると思いますが、 Kotlinではスマートキャストのおかげか大活躍していますね。
ちなみにinstanceof
の内部の動きに関してはJJUG CCC Fall 2018で発表された方がいて
大変勉強になりました。以下のリンクがその時のスライドです。
参考にどうぞ
楽しく見ていただいた方はチャンネル登録お願いします。(?)
追記
スマートキャストが動いている例もやってみました。
sealed class A{ class B(var num:Int):A() class C(var str:String):A() class D(var double: Double,var int: Int):A() } fun test(hoge:Int){ val v:A= if(hoge==0){ A.B(1) }else if(hoge==1){ A.C("1") } else { A.D(1.0,2) } when(v){ is A.B-> print(v.num) is A.C-> print(v.str) is A.D-> print(listOf(v.double,v.int)) } }
逆翻訳後
/* クラス定義は省略します */ public final class TestKt { public static final void test(int hoge) { A v = hoge == 0 ? (A)new A.B(1) : (hoge == 1 ? (A)new A.C("1") : (A)new A.D(1.0, 2)); A a = v; if (a instanceof A.B) { int n = ((A.B)v).getNum(); System.out.print(n); } else if (a instanceof A.C) { String string = ((A.C)v).getStr(); System.out.print((Object)string); } else if (a instanceof A.D) { List list = CollectionsKt.listOf((Object[])new Object[]{((A.D)v).getDouble(), ((A.D)v).getInt()}); System.out.print(list); } } }
普通にダウンキャストと同じバイトコードになるようですね。