Java
Kotlin

Kotlinのプログラムを逆コンパイル:Dataクラス編

Javaプログラマーなら面倒なsetter, getter,hashcode,toStringの実装に一度はうんざりしたことがあるのではないでしょうか?

IDEが自動で実装したり、lombokのようなツールを使うことでこの問題を深く考えないようにしているのではないでしょうか?

KotlinではClass宣言時にdataという修飾子をつけることでこれらの面倒な宣言を自動生成する仕組みがあります

Persionクラス
data class Person(val name:String, val age: Int)

Persionクラスを利用するコード
    var bob =  Person("Bob",33)
    var bob2 = Person("Bob",33)
    println(bob===bob2)//false
    println(bob==bob2)//true
    println(bob.equals(bob2))//true
    println(bob.hashCode())//2075948
    println(bob.toString())//Person(name=Bob, age=33)

JADで逆コンパイル

personクラスを逆コンパイルして、自動実装されているコードをJavaに変換して見ます

$ jad Person.class 
Parsing Person.class... Generating Person.jad
Couldn't fully decompile method hashCode

hashcodeのメソッドが逆コンパイルできませんでした。
こちらはコードの挙動をブログにまとめましたので興味のある方は一読ください。

Personクラスの逆コンパイル結果
import kotlin.jvm.internal.Intrinsics;

public final class Person
{

    public final String getName()
    {
        return name;
    }

    public final int getAge()
    {
        return age;
    }

    public Person(String name, int age)
    {
        Intrinsics.checkParameterIsNotNull(name, "name");
        super();
        this.name = name;
        this.age = age;
    }

    public final String component1()
    {
        return name;
    }

    public final int component2()
    {
        return age;
    }

    public final Person copy(String name, int age)
    {
        Intrinsics.checkParameterIsNotNull(name, "name");
        return new Person(name, age);
    }

    public static volatile Person copy$default(Person person, String s, int i, int j, Object obj)
    {
        if((j & 1) != 0)
            s = person.name;
        if((j & 2) != 0)
            i = person.age;
        return person.copy(s, i);
    }

    public String toString()
    {
        return (new StringBuilder()).append("Person(name=").append(name).append(", age=").append(age).append(")").toString();
    }

    public int hashCode()
    {
        name;
        if(name == null) goto _L2; else goto _L1
_L1:
        hashCode();
          goto _L3
_L2:
        JVM INSTR pop ;
        false;
_L3:
        31;
        JVM INSTR imul ;
        age;
        JVM INSTR iadd ;
        return;
    }

    public boolean equals(Object obj)
    {
label0:
        {
            if(this != obj)
            {
                if(!(obj instanceof Person))
                    break label0;
                Person person = (Person)obj;
                if(!Intrinsics.areEqual(name, person.name) || (age != person.age))
                    break label0;
            }
            return true;
        }
        return false;
    }

    private final String name;
    private final int age;
}

hashCode,equals,toString,copy,#copyの自動生成が確認できました。