Show Kotlin Bytecode便利!
今回はKotlinを知るために便利な、もしくは困ったときにヒントになるであろう、
Kotlin BytecodeをIntelliJ IDEAで見ることの出来る機能を紹介します。
今更感のあるTips的なやつです。
※私の確認環境はIntelliJ IDEA 15.0.6 CEです。
手順
まず、Kotlinのコードを書きます。
main関数でhello,worldですね。極めて一般的です。
fun helloworld() {
println("コンニチワセカイ")
}
Tools>Kotlin>Show Kotlin Bytecodeを選びます。
もしくはshift2回でsearch everywhereからも選択可能です。
そうすると、なんと、Kotlinのコンパイル後のバイトコードが現れます!!
kotlincしてJavaのクラスファイルになったものをjavapしたものって感じです。
さらに、右上のDecompileというボタンを押すと。。。
KotlinがJava側からどう見えるかが分かります!
メリット
この機能を使いながらKotlinのコードを書くことは以下の様なメリットがあると思います。
- Javaから呼び出しやすい
- 自分の書いたKotlinのコードの意味を理解しやすい
- より有効なコードを書くヒントになる
- 良くないコーディングやハマりどころを解決するヒントになる
Kotlinのコードを色々見てみよう
例えば、簡単なクラスを作ってみましょう。
class Person(val age : Int, val name : String)これがJavaにdecompileするとこうなります。
import kotlin.Metadata; import kotlin.jvm.internal.Intrinsics; import org.jetbrains.annotations.NotNull; @Metadata( mv = {1, 1, 1}, bv = {1, 0, 0}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\b\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0006\u0018\u00002\u00020\u0001B\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\u000b"}, d2 = {"LPerson;", "", "age", "", "name", "", "(ILjava/lang/String;)V", "getAge", "()I", "getName", "()Ljava/lang/String;", "production sources for module core"} ) public final class Person { private final int age; @NotNull private final String name; public final int getAge() { return this.age; } @NotNull public final String getName() { return this.name; } public Person(int age, @NotNull String name) { Intrinsics.checkParameterIsNotNull(name, "name"); super(); this.age = age; this.name = name; } }
これだけでも
- メタデータを持っていること
- getterが自動で生成されること
- クラスも、フィールドもfinalであること
- @NotNullによるチェックが行われていること
などが分かります!
そしてさっきのコードにdataを付け加えましょう。
data class Person(val age : Int, val name : String)
そうすると、こうなります。
import kotlin.Metadata; import kotlin.jvm.internal.Intrinsics; import org.jetbrains.annotations.NotNull; @Metadata( mv = {1, 1, 1}, bv = {1, 0, 0}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\b\n\u0000\n\u0002\u0010\u000e\n\u0002\b\t\b\u0086\b\u0018\u00002\u00020\u0001B\u0015\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0005¢\u0006\u0002\u0010\u0006J\t\u0010\u000b\u001a\u00020\u0003HÆ\u0003J\t\u0010\f\u001a\u00020\u0005HÆ\u0003J\u001d\u0010\r\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00032\b\b\u0002\u0010\u0004\u001a\u00020\u0005HÆ\u0001R\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\u000e"}, d2 = {"LPerson;", "", "age", "", "name", "", "(ILjava/lang/String;)V", "getAge", "()I", "getName", "()Ljava/lang/String;", "component1", "component2", "copy", "production sources for module core"} ) public final class Person { private final int age; @NotNull private final String name; public final int getAge() { return this.age; } @NotNull public final String getName() { return this.name; } public Person(int age, @NotNull String name) { Intrinsics.checkParameterIsNotNull(name, "name"); super(); this.age = age; this.name = name; } public final int component1() { return this.age; } @NotNull public final String component2() { return this.name; } @NotNull public final Person copy(int age, @NotNull String name) { Intrinsics.checkParameterIsNotNull(name, "name"); return new Person(age, name); } // $FF: synthetic method // $FF: bridge method @NotNull public static Person copy$default(Person var0, int var1, String var2, int var3, Object var4) { if(var4 != null) { throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: copy"); } else { if((var3 & 1) != 0) { var1 = var0.age; } if((var3 & 2) != 0) { var2 = var0.name; } return var0.copy(var1, var2); } } public String toString() { return "Person(age=" + this.age + ", name=" + this.name + ")"; } public int hashCode() { return this.age * 31 + (this.name != null?this.name.hashCode():0); } public boolean equals(Object var1) { if(this != var1) { if(var1 instanceof Person) { Person var2 = (Person)var1; if(this.age == var2.age && Intrinsics.areEqual(this.name, var2.name)) { return true; } } return false; } else { return true; } } }
component1,component2,copy,equals,hashcodeなど
色々なメソッドが増えていることが分かりますね!
この先は自分で確かめてみて欲しい
他にもsealed classやenum class、when式や拡張関数、object、delegateなんてものもあります。
実際どのような動きをしているのかIntelliJ IDEAで確かめてみてください!
0 件のコメント:
コメントを投稿