Android StudioでのLombokの導入手順と対応状況

Wed Apr 30, 2014

Lombokとは

Very spicy additions to the Java programming language.

ビルド時にAST変換をしてメソッドを生やしたり後処理を追加したり、便利なコードを自動生成する(ソースコードを書き出すのではなく生成されるバイナリを書き換える)ライブラリです。

導入手順

1. build.gradleのdependenciesに追加します

provided 'org.projectlombok:lombok:1.12.2'

2. Preferences > Plugins > Browse Repositories > Lombok Plugin をインストールします

プラグインがなくてもビルドはできますが、入れないと警告が出たり定義にジャンプしたりできないので入れます。

Androidアプリ開発で使えそうなもの(行数は目安です)

@Data

Getter、Setter、ConstructorおよびtoString、equals、hashCodeの自動生成を行う

ビルド前(5行)

@Data
public class DataExample {
    private final String name;
    @Setter(AccessLevel.PACKAGE) private int age;
}

ビルド後(45行)

public class DataExample {
    private final String name;
    private int age;

    public DataExample(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    @Override
    public String toString() {
        return "DataExample(" + this.getName() + ", " + this.getAge() + ")";
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof DataExample)) return false;
        DataExample other = (DataExample) o;
        if (!other.canEqual((Object)this)) return false;
        if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
        if (this.getAge() != other.getAge()) return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        result = (result*PRIME) + (this.getName() == null ? 0 : this.getName().hashCode());
        result = (result*PRIME) + this.getAge();
        return result;
    }
}

@Builder

Builderクラスの自動生成を行う。

ビルド前(5行)

@Builder
public class BuilderExample {
    private String name;
    private int age;
}

ビルド後(39行)

public class BuilderExample {
    private String name;
    private int age;

    BuilderExample(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static BuilderExampleBuilder builder() {
        return new BuilderExampleBuilder();
    }

    public static class BuilderExampleBuilder {
        private String name;
        private int age;

        BuilderExampleBuilder() {
        }

        public BuilderExampleBuilder name(String name) {
            this.name = name;
            return this;
        }

        public BuilderExampleBuilder age(int age) {
            this.age = age;
            return this;
        }

        public BuilderExample build() {
            return new BuilderExample(name, age);
        }

        @java.lang.Override
        public String toString() {
            return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ")";
        }
    }
}

@Cleanup

リソースをクローズするコードの自動生成を行う。

ビルド前(12行)

public class CleanupExample {
    public static void main(String[] args) throws IOException {
        @Cleanup InputStream in = new FileInputStream(args[0]);
        @Cleanup OutputStream out = new FileOutputStream(args[1]);
        byte[] b = new byte[10000];
        while (true) {
            int r = in.read(b);
            if (r == -1) break;
            out.write(b, 0, r);
        }
    }
}

ビルド後(24行)

public class CleanupExample {
    public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream(args[0]);
        try {
            OutputStream out = new FileOutputStream(args[1]);
            try {
                byte[] b = new byte[10000];
                while (true) {
                    int r = in.read(b);
                    if (r == -1) break;
                    out.write(b, 0, r);
                }
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }
}

val

型を省略して再代入不可の変数を宣言できる(Scalaのval相当) ビルドはできて実行もできるけどプラグインが対応していなくて唐辛子のように赤い警告が出る。

IntelliJプラグインの対応表

Updated Feb 16, 2014

所感

  • ライブラリ自体はコンパイル時だけに作用してアプリには含まれないので容量が増えなくてグッド
  • ビルド時間はそんなに気にならなさそう
  • コード量は減るけどIDEのリファクタリングが効かなくなったり、JVMのテストから生成したコードが見えなかったり、未知のバグにハマることがありそう

良いか悪いかでいうと、プラマイゼロくらいな気がします。

唐辛子について

韓国人の同僚からキムチは昔はただの漬物だったんだけど、日本から唐辛子が入ってくるようになって今のように辛くなったという話を聞いた。 なんとなく「唐」って付いてたから中国の四川あたりに生えてたのが韓国に伝わったのかなと思っていたので、へえぇと思って調べてみたら、唐辛子は中南米が原産地で、メキシコでの歴史は紀元前6000年に遡るくらい古くて、15世紀の大航海時代に世界に広まったらしい。 「唐」っていうのは漠然と「外国」を指す語だったらしい。

この手の辛いものは殺菌作用が強いので食中毒を防ぐとも言われていて、特に熱い地方で多く使われてたり、また殺菌のほかに害虫を減らす目的で栽培されたり、園芸では虫害を減らす目的で一緒に栽培されることがあったり、鑑賞するための唐辛子の品種もある。

観賞用のゴシキトウガラシ

コロンブスはインドの胡椒を目指して西インド諸島(カリブ)を発見して、そこで見つけた唐辛子を胡椒と勘違いしたまま世界に広まってしまってred pepperとpepperの名称を混乱させたという話もあって、伝来史もおもしろかった。



  « Previous: Next: »