kagamihogeの日記

kagamihogeの日記です。

Java SE 7の新機能をためす

イマサラな感じではありますが。自分でためしたことがなかったので、実際にコードを書くなどして試してみる。Java Programming Language EnhancementsのEnhancements in Java SE 7の項を見ながらこのエントリを書いてます。テキトーに試してるだけなので、間違ってること書いてる可能性もあります。よって、正確な情報についてはリンク先のドキュメントを参照してください。

環境

  • jdk1.7.0_09
  • Eclipse4.2.0 SR1

Binary Literals

その名前のとおり、バイナリのリテラル形式が使えるようになった。可読性向上のためのもの。

byte aByte = (byte)0b11111111;
short aShort = (short)0b11111111000000001111111100000000;
long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;

Javaというか業務システムだとあまりやらないんだけど、こういうビットマップ的な表現が書きやすくなる感じですね。

public static final short[] BLOCK = {
    (short)0b11111111,
    (short)0b11000001,
    (short)0b10100001,
    (short)0b10010001,
    (short)0b10001001,
    (short)0b10000101,
    (short)0b10000011,
    (short)0b11111111,
};

Underscores in Numeric Literals

数値リテラルをアンダースコア(_)で区切れるようになった。これも、可読性向上のためのもの。

long creditCardNumber = 1234_5678_9012_3456L;
long hexBytes = 0xFF_EC_DE_5E;

サンプルコードはドキュメントからコピペしてきたもの。何らかのコード体系を数値型でもっていて、桁数の区切りが意味を持つ場合とかに便利そうですかね。

Strings in switch Statements

switchにStringが使えるようになりました。

String version = "hoge1.1";
switch (version) {
    case "hoge1.1":
        System.out.println("1.1");
        break;
    case "hoge2.0":
        System.out.println("2.0");
        break;
    default:
        break;
}

文字列の中身によって分岐させる、って型が強い文化圏のJavaではアンマリやらないような気もするけど。ただまぁ使う時には使うので、これも便利といえば便利か。

Type Inference for Generic Instance Creation

インスタンス作るときのジェネリクス指定がラクになりますよ、というもの。

サンプルのコードそのまんまコピペですが。下記のように、new HashMapのうしろが<>だけで済むようになった。

Map<String, List<String>> myMap = new HashMap<>();

さすがに型推論とまでは行かないようだけれど、地味に便利そう。

Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods

これは何をやってくれるのかは、リンク先のソースコード例を見たほうが早い。要するに、可変長引数にジェネリクス型を指定していてClassCastExceptionが起こる恐れのあるコードにwariningを出すようにしましたよ、というもの。Javaジェネリクスは、コンパイラからするとtype erasureであり、たやすくヒープ汚染しちゃうんですよ、てなことが書かれている……と思う。可変長引数は見た目がジェネリクスであっても配列になるので特に危険ってな感じなんですかね。

The try-with-resources Statement

これはもう見たまんまといいますか。tryを抜けるときにリソースを自動でクローズしてくれる便利な構文。

try (
    BufferedReader br = new BufferedReader(new FileReader(new File("hoge.txt")));
    BufferedWriter bw = new BufferedWriter(new FileWriter(new File("hoge_out.txt")))
) {
    String s;
    while ((s = br.readLine()) != null){
        bw.write(s + System.getProperty("line.separator"));
    }
} catch (IOException e) {
    e.printStackTrace();
}

Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking

Catching Multiple Exception Typesてのは、これまたみたまんまなのですが。複数の異なる型の例外を単一ブロックにまとめてしまえる。結局ログ出力してthrowするだけなんや、というのを省略するとかに使う。

try {
    th();
} catch (IOException | SQLException e) {
    e.printStackTrace();
}

もう一つRethrowing Exceptions with Improved Type Checkingも、実際のコード見たほうがはやい。

public static void th() throws Exception {
    int i = 0;
    try {
        if (i == 0) {
            new IOException();
        }
        if (i == 1) {
            new SQLException();
        }
    } catch (Exception e) {
        throw e;
    }
}

意味の無いコードで申し訳ないのだが…java6以前では上のように異なる型の例外をスローしなおそうとしたときthrows Exceptionと書かざるを得なかった。が、java7以降では下記のように書けるようになり、例外の型を明示できるようになった。Multiple Exception Typesとの合わせ技で使ってね、というところなんでしょう。ちなみに、リンク先のドキュメントではコンパイラが何をやっているのかについてカンタンな解説が載っている。

public static void th() throws IOException, SQLException {
   //...
}