Java7 Project Coinの再確認とAssertJを試してみる

Java7 Project Coinの再確認とAssertJを試してみたメモです。

今更ながらJava7 Project Coinについて再確認しました。
あとはAssertJを使ってみたかったので、hamcrestで書いてあったテストを
AssertJで書き直してみました。

Project Coin

Project CoinはJava7で加わった、小さな変更のまとまりの総称です。
Java6までで使いにくかったものを使いやすくした変更です。

Java7からもう5年も経っているので、普通に使っているものばかりです。

switch文での文字列使用

switch文のcase式で文字列が使用できるようになりました。

    @Test
    public void swithで文字列が使用できる() throws Exception {
        String str = "bar";

        switch (str) {
            case "foo":
                str += "1";
                break;
            case "bar":
                str += "2";
                break;
            case "foobar":
                str += "3";
                break;
            default:
                str += "4";
        }
        assertThat(str).isEqualTo("bar2");
    }
2進数リテラル

2進数をリテラルで書けるようになりました。
頭に0bまたは0Bをつけます。

    @Test
    public void 二進数リテラルが使用できる() throws Exception {
        int a = 0b0100;

        assertThat(a).isEqualTo(4);
    }
数値リテラルでの区切り文字

数値リテラルで区切り文字(アンダースコア)を入れて読みやすくすることができるようになりました。
perlでは昔から出来ていましたが、Javaでも出来るようになりました。
1,000,000のように3ケタずつカンマの代わりに入れたり、
2進数で4ケタずつ入れるなどすると便利です。

    @Test
    public void 数値リテラルで区切り文字が使用できる() throws Exception {
        int a = 1_000_000;
        int b = 0b0001_1000;

        assertThat(a).isEqualTo(1000000);
        assertThat(b).isEqualTo(24);
    }
例外のマルチキャッチ

同じ例外処理を行う場合、catch文で例外をまとめて書けるようになりました。
まとめる場合は例外を|(パイプ)でつなげます。
ただし、継承関係にある例外はまとめられません。

    @Test
    public void 例外のマルチキャッチが可能() throws Exception {
        String message = "";
        try {
            Class clazz = Class.forName("Sample");
        } catch (ClassNotFoundException | ClassCastException e) {
            message = e.getMessage();
        }

        assertThat(message).isEqualTo("Sample");
    }
ダイヤモンド演算子

ジェネリクスを使用したクラスをnewで生成する場合、型指定を省略できるようになりました。
今まではnewする場合に2度記述する必要があり冗長でしたが、
省略しても型推論できるため、省略できます。

    @Test
    public void ダイヤモンド演算子が使用できる() throws Exception {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        assertThat(list).containsOnly("aaa", "bbb", "ccc");
    }
リソースの自動クローズ

リソースのクローズ処理はfinallyを利用して記述するのが一般的でしたが、冗長でした。
try-with-resources構文を利用すると、リソースの自動クローズをしてくれます。
書き方は、tryのカッコの中に利用するリソースのオープン処理を記述します。

    @Test
    public void リソースが自動クローズされる() throws Exception {
        StringBuilder sb = new StringBuilder();

        try (BufferedReader reader = new BufferedReader(new FileReader("src/main/java/javase7/samplefile.txt"))) {
            String line;
            while((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        assertThat(sb.toString()).isEqualTo("abcdefg");
    }
可変長引数の警告抑止

可変長引数を取るメソッドで、ジェネリクスを使用した変数に代入しようとすると警告が出ます。
@SafeVarargsアノテーションを付与することで、警告の出力を抑止できるようになります。

    @Test
    public void 安全な可変長引数() throws Exception {
        List<String> list = new ArrayList<>();
        List actual = add(list, "aaa", "bbb", "ccc");

        String[] expected = {"aaa", "bbb", "ccc"};

        assertThat(actual).containsOnly(expected);
    }

    @SafeVarargs
    public static <T> List<T> add(List<T> list, T... t) {
        Arrays.stream(t).forEach(list::add);
        return list;
    }

テストコード

今回のテストコードの全文です。

ProjectCoinTest.java

package javase7;

import org.junit.Test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

public class ProjectCoinTest {
    @Test
    public void swithで文字列が使用できる() throws Exception {
        String str = "bar";

        switch (str) {
            case "foo":
                str += "1";
                break;
            case "bar":
                str += "2";
                break;
            case "foobar":
                str += "3";
                break;
            default:
                str += "4";
        }
        assertThat(str).isEqualTo("bar2");
    }

    @Test
    public void 二進数リテラルが使用できる() throws Exception {
        int a = 0b0100;

        assertThat(a).isEqualTo(4);
    }

    @Test
    public void 数値リテラルで区切り文字が使用できる() throws Exception {
        int a = 1_000_000;
        int b = 0b0001_1000;

        assertThat(a).isEqualTo(1000000);
        assertThat(b).isEqualTo(24);
    }

    @Test
    public void 例外のマルチキャッチが可能() throws Exception {
        String message = "";
        try {
            Class clazz = Class.forName("Sample");
        } catch (ClassNotFoundException | ClassCastException e) {
            message = e.getMessage();
        }

        assertThat(message).isEqualTo("Sample");
    }

    @Test
    public void ダイヤモンド演算子が使用できる() throws Exception {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        assertThat(list).containsOnly("aaa", "bbb", "ccc");
    }

    @Test
    public void リソースが自動クローズされる() throws Exception {
        StringBuilder sb = new StringBuilder();

        try (BufferedReader reader = new BufferedReader(new FileReader("src/main/java/javase7/samplefile.txt"))) {
            String line;
            while((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        assertThat(sb.toString()).isEqualTo("abcdefg");
    }

    @Test
    public void 安全な可変長引数() throws Exception {
        List<String> list = new ArrayList<>();
        List actual = add(list, "aaa", "bbb", "ccc");

        String[] expected = {"aaa", "bbb", "ccc"};

        assertThat(actual).containsOnly(expected);
    }

    @SafeVarargs
    public static <T> List<T> add(List<T> list, T... t) {
        Arrays.stream(t).forEach(list::add);
        return list;
    }
}

ソースは一応あげときました。
github.com

終わり。