JDK 7の新機能 Peoject Coin編(その1)
先日、JDK 7の開発者プレビューと、JDK 7に対応したNetBeans 7.0 Beta 2がそれぞれリリースされました。せっかくなのでJDK 7の新機能をおさらいしつつ、実際にNetBeansを使って試してみたいと思います*1。
JDK 7の新機能についてはこのページに一覧がまとめられています。まずは最も身近とも言える「Project Coin」からいってみましょう。Project Coinは、個別に仕様化するほどではない細かな文法の変更や追加などの実装を進めたプロジェクトです。JCPでは「JSR 334: Small language enhancements」として登録されています(現在、ドキュメントがダウンロードできます)。現在のところ、JSR 334にはJava SE 7に搭載する新機能として次のものが挙げられており、いずれもJDK 7ではすでに実装が完了しています。
- Stringによるswitch文
- 2進数リテラルとアンダースコア付き数値リテラル
- 複数例外のキャッチおよび例外の安全な再スロー
- 型推論によるジェネリクスのオブジェクト生成(ダイアモンド)
- リソース付きのtry-catch
- 可変長引数を使うメソッド呼び出しの警告を抑制(@SafeVarargsアノテーション)
Stringによるswitch文
まずStringを使用したswicth文についてですが、これはswitchの条件に文字列リテラルが使えるようになったということです。次のような感じです。
static void testStringSwitch(String str) { switch (str) { case "hoge": System.out.println("ほげほげ"); break; case "piyo": System.out.println("ぴよぴよ"); break; default: System.out.println("デフォルト"); break; } }
strにnullを渡すをNullPoinerExceptionがスローされます。これはIntegerなどの場合と同様ですね。
switch文のこの拡張は、現時点ではJVMには影響を与えません(将来サポートされる可能性はあります)。JVMではswitchを扱う命令としてlookupswitchとtableswitchがあるわけですが、これらは依然として文字列リテラルをサポートしてないということです。ではどうやって比較しているのかというと、コンパイラは文字列をバイトコードシーケンスに変換し、それを比較に利用しているとのことです*2。
2進数リテラル
Javaでは、"0x"を数値の前に付けて16進数の数値を表すことができます。JDK 7では、同じような方法で2進数の数値を表すこともできるようになりました。2進数は、数値の前に"0b"または"0B"を付けて表現します。次のような感じです。
int binary = 0b011001; System.out.println(binary); int binary2 = 0B110100; System.out.println(binary2);
出力は以下のように普通の10進数形式になります。
25 52
次のような表記はできません。これは0xの場合と同じです。
int binary3 = 0b12345; // コンパイルエラー
アンダースコア付き数値リテラル
数値リテラルについてはもうひとつ変更があります。数値の途中に「1_234_567」のようにアンダースコア("_")を入れられるようになったことです。これは内部的には普通に「1234567」として扱われます。「1,23,567」のような区切り文字付きの数値と同じようなものと考えていいでしょう。この変更はコードの可読性を上げるために採用されました。アンダースコアは連続して付けることもできますが、数値の先頭や最後に付けることはできません。
int withUnderscore = 123_456_789; System.out.println(withUnderscore); int withUnderscore2 = 9_8_7_6_5; System.out.println(withUnderscore2); int withUnderscore3 = 123__456; System.out.println(withUnderscore3);
出力結果は次のようになります。
123456789 98765 123456
次のような書き方はコンパイルエラーになります。
int withUnderscore4 = _123456; // コンパイルエラー int withUnderscore5 = 123456_; // コンパイルエラー
通常の数値リテラルと同じなので、次のようなこともできます。
for (int i = 0; i < 1_00; i++) { ... }
2進数リテラルや16進数リテラルなどの中で使うこともできますが、これも先頭や末尾に付けるのはダメです。
int binary4 = 0b0_110_01; int hex = 0x123_abc; //int binary5 = 0b_011001; // コンパイルエラー