Help us understand the problem. What is going on with this article?

Javaでコードを書くのがだるすぎたけどLombok使ったら思いのほか楽しかった

More than 5 years have passed since last update.

「Lombok、便利そうだけどまあそんなに使わないかなあ」と思ってたんだけど試しに使ってみたらかなり快感だったのでメモ。

Javaのだるさ

Javaでプログラムを書いているとよく「intのtype, Stringのnameというフィールドを持つだけの、特定の処理などは含まないHogeクラスを作ろう。まあ普通に文字列表現もあってequalsによる比較とかもできるように」のように思います。

Hoge.java
package org.hogel;

public class Hoge {

    private int type;
    private String name;

    public Hoge() {
    }

    public Hoge(int type, String name) {
        this.type = type;
        this.name = name;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return type + (name == null ? 0 : name.hashCode());
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        } else if (obj == null || !(obj instanceof Hoge)) {
            return false;
        }
        Hoge other = (Hoge) obj;
        if (type != other.getType()) {
            return false;
        }
        return name == other.getName() || name != null && name.equals(other.getName());
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        return builder.append("Hoge(type=").append(type).append(", name=").append(name).append(")").toString();
    }
}

うっ、だるい

なんてコードの長さでしょう。ディスプレイのサイズは有限なのです、こんな長いコードを表示するのには何年もかかってしまいます。

そうだ、困ったときのCommonsだ

Javaで困ったときはとりあえずApache Commonsを頼りにしましょう。

Commons Langという便利なライブラリにはこういった独自クラスを作るときに有用な機能が含まれています。

Hoge.java
package org.hogel;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

public class Hoge {

    private int type;
    private String name;

    public Hoge() {
    }

    public Hoge(int type, String name) {
        this.type = type;
        this.name = name;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

    @Override
    public String toString() {
        // Hoge[type=1,name=a]のような形式で出力される
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}

hashCode, equals, toStringメソッドの中身がすべて一行になりました。ああしかしやっぱりめんどうです、めんどうなので 一々こんなクラス作るのをやめてListやらMapやらを組み合わせてしまおうか、なんて思ってしまいます。

そうだ、Lombokがある

さてここでLombok。百聞は一見にしかず。Lombokを使うと上述したコードがこんなことになります。

Hoge.java
package org.hogel;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Hoge {
    private int type;
    private String name;
}

おや、ほとんど何もなくなっていますね。でもこれで上に書いた2つのコードとほとんど同じ挙動をするのです。試しにこんなテストコードで実行してみます。

HogeTest.java
package org.hogel;

import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;

public class HogeTest {
    @Test
    public void hogeBean() {
        Hoge a1 = new Hoge(1, "a");
        Hoge a2 = new Hoge(1, "a");
        Hoge b = new Hoge(2, "b");

        System.err.println("a1.getType(): "+ a1.getType());
        System.err.println("a1.getName(): "+ a1.getName());
        System.err.println();

        System.err.println("a1: " + a1);
        System.err.println("b: " + b);
        System.err.println();

        System.err.println("a1 == a2: " + (a1 == a2));
        System.err.println("a1 == b: " + (a1 == b));
        System.err.println();

        System.err.println("a1.equals(a2): " + a1.equals(a2));
        System.err.println("a1.equals(b): " + a1.equals(b));
        System.err.println();

        System.err.println("a1.hashCode(): " + a1.hashCode());
        System.err.println("a2.hashCode(): " + a2.hashCode());
        System.err.println("b.hashCode(): " + b.hashCode());
        System.err.println();

        assertThat(a1, is(a2));
        assertThat(a1, not(b));

        assertThat(a1.hashCode(), is(a2.hashCode()));
    }
}

定義もしていないコンストラクタやgetType、getNameなどを呼んでいます。それの実行結果がこうなります。

a1.getType(): 1
a1.getName(): a

a1: Hoge(type=1, name=a)
b: Hoge(type=2, name=b)

a1 == a2: false
a1 == b: false

a1.equals(a2): true
a1.equals(b): false

a1.hashCode(): 1089
a2.hashCode(): 1089
b.hashCode(): 1121

なんだか知らんがうまいこと動作していますね。Lombok、すげー。

IDEなしでJavaを書くなんてのはただの苦行ですし、Lombokは各IDEにも対応しています
lombok-intellij.png

詳細や更に便利な機能などはLombokのページでご確認ください。valなんて使いはじめるともうJavaなのかなんなのかわからなくなってきてとても楽しいと思います。

hogelog
hogelog http://hogel.org/
http://hogel.org/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした