こんにちは、中村です。
Java7がリリースされて1年経ちましたが、
きちんと調べたことがなかったので、調査をまとめておこうかと思います。
題名にも書きましたが、Java7にはProject Coinというプロジェクトがあり、
小さい言語仕様の変更を行いました。
その言語仕様の変更を簡単にまとめたいと思います。
まず、変更点の概要を紹介します。
- switch文に文字列が使用可能になった
- 2進数リテラルを表現可能になった
- 整数リテラルに区切り文字が使用可能になった
- 例外のマルチキャッチが可能になった
- 例外の再スロー時にthrowsが必要なくなった
- ジェネリクスが一部省略可能になった
- リソースのオートクローズが可能になった
- 可変長引数の指定で警告が発生しないようになった
次にそれぞれを簡単に説明していきます。
1. switch文に文字列が使用可能になった
switch文にはbyte, char, int, shortとそれらのラッパークラス、列挙型しか使用できませんでした。
しかし、Java7では文字列が指定可能になりました。
2. 2進数リテラルを表現可能になった
Javaではすでに8進数リテラル、16進数リテラルを表現可能(8進数:0NNN 16進数:0xNN)でしたが、
2進数を表現する事ができませんでした。
しかし、Java7では2進数リテラルが表現可能になりました。
(0bNNNN or 0BNNNN)
3. 整数リテラルに区切り文字が使用可能になった
整数リテラルは、桁数が大きくなると可読性が低くなりがちでした。
(特に8,16進数)
Java7では、整数リテラルの区切り文字として”_”(アンダースコア)が使用可能となりました。
例:
- 0xF9A09B⇒0xF9_A0_9B
- 0b100100110101⇒0b1001_0011_0101
- 0684⇒0_684
※8進数のみリテラル用文字列(0x, 0b, 0)直後に使用可能
4. 例外のマルチキャッチが可能になった
try-catch節を使用して例外をキャッチする際、異なる例外で同じ処理を行う場合、以下の様な記述となる。
FileInputStream fis = null; try { fis = new FileInputStream(new File("test.txt")); } catch (FileNotFoundException fnfe) { System.out.println("えらーです。"); } catch (SecurityException se) { System.out.println("えらーです。"); } finally { // クローズ処理 }
しかし、Java7では”|”を区切り文字に複数の例外を一度にキャッチすることができるようになりました。
例:
FileInputStream fis = null; try { fis = new FileInputStream(new File("test.txt")); } catch (FileNotFoundException | SecurityException ex) { System.out.println("えらーです。"); } finally { // クローズ処理 }
5. 例外の再スロー時にthrowsが必要なくなった
FileInputStream fis = null; try { fis = new FileInputStream(new File("test.txt")); } catch (FileNotFoundException fnfe) { throw fnfe; } finally { // クローズ処理 }
例外の再スローとは、上記のような処理のことを指します。
上記の例では、FileNotFoundException例外が発生した時にFileNotFoundExceptionを再スローしているため、
このメソッドにthrowsを追加しなければなりませんでした。
しかし、Java7ではキャッチした例外をそのまま再スローする場合に限り、throwsを追加する必要がなくなりました。
6. ジェネリクスが一部省略可能になった
ジェネリクスを必要とするオブジェクトのインスタンスを生成する際、ジェネリクスを省略可能になりました。
例:
List<String> list1 = new ArrayList<>(); List<List<String>> list2 = new ArrayList<>(); List<List<List<String>>> list3 = new ArrayList<>();
省略した際の<>はダイヤモンドオペレータと呼びます。
※ただし、Class<T>クラスのコンストラクタが”Class<T>(T tea)”のような場合、
Class<Number> cls = new Class<>(10);
のような使い方をすると、ダイヤモンドオペレータがInteger型だとご認識してしまいます。
(10がNumber型とは読み取れない)
必ずしも正しく動くわけではないので、注意が必要です。
7. リソースのオートクローズが可能になった
これまでのJavaのリソースに対するクローズ処理は大変冗長で、
クロース忘れも発生していました。
例えば、
InputStream is = null; OutputStream os = null; try { is = new FileInputStream(src); os = new FileOutputStream(src); byte[] buf = new byte[1024]; int size; while((size = is.read(buf)) >= 0) { os.write(buf, 0, size); } } catch (IOException ex) { System.err.println("エラーです。"); } finally { try { if (is != null) { is.close(); } if (os != null) { os.close(); } } catch (IOException ex) {} }
このコードを見れば分かる通り、クローズ処理を行なっているfinally節が大変冗長になっています。
しかし、Java7では短いコードで、クローズ忘れも防止できるようになりました。
上記コードをJava7で記述すると以下のようになります。
try (InputStream is = new FileInputStream(src); OutputStream os = new FileOutputStream(src)) { byte[] buf = new byte[1024]; int size; while((size = is.read(buf)) >= 0) { os.write(buf, 0, size); } } catch (IOException ex) { System.err.println("エラーです。"); }
このように記述するだけで、try節を抜けた時点でリソースがクローズされます。
8. 可変長引数の指定で警告が発生しないようになった
これはまず以下のコードを御覧ください。
List<List<String>> listInList = Arrays.asList(Arrays.asList("",""),Arrays.asList("",""));
これまでのJavaでは、警告が発生します(可変引数にジェネリクスを指定しているため)。
そのため、@SuppressWarnings(“unchecked”)を記述する必要がありました。
しかし、Java7では上記警告が発生しなくなりました。
以上で、Project Coinの仕様変更点の紹介を終わります。
Java7はまだまだ成熟されていないですし、最近脆弱性も発見されたので、
使われることはまだ先になりそうですが、もし使うことになった時に参考にしてもらえればと思います。