Java SE 7 Project Coin
2012/08/16 村上 直広
Project Coin は今まで使いにくかった文法を使いやすくすることを目標にしたプロジェクトです。
Javaには主要なプロジェクトとして、Project Coinのほかにも「Project Lambda」「Project Jigsaw」があり、Java8以降に適用されていきます。
Project Lambdaはラムダ式の採用に関するプロジェクトで、2013年9月リリース予定のJava SE 8で採用予定です。Project JigsawはJavaのモジュール化に関するプロジェクトで、2015年リリース予定のJava SE 9で採用予定です。
(2012年8月現在)
Java SE 8では、他にもビッグデータへの対応やマルチテナントへの対応があります。
今回はJava SE 7(以下Java7)で追加されたProject Coinについて下記に説明いたします。
- Binary Literals – バイナリリテラル
- Underscores in Numeric Literals – アンダースコア入り数値リテラル
- Strings in switch Statements – switch文のcaseラベルに文字列を使える
- Type Inference for Generic Instance Creation – コンストラクタ呼び出し時の型推論
- The try-with-resources Statement – リソース管理用構文の追加
- Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking – 複数のcatch節、例外の再スローについての改善
1. Binary Literals
(バイナリリテラル)
「0b」または「0B」を接頭辞にすることで、2進数表現できるようになりました。
byte b = 0b1010101; // 85 short s = 0b001111111011111; // 8159 int i = 0b00111111011111011111111011111110; // 1065221886 long l = 0b0010000101000101101000010100010110100001010001011010000101000101L; // 2397499697075167557
各変数に代入する時はint型で処理しているので、long型を使用する場合は「L」を付けることに注意してください。
2. Underscores in Numeric Literals
(アンダースコア入り数値リテラル)
数値リテラルに「_(アンダースコア)」を含めるようになりました。
例えば、クレジットカードナンバーを変数に持つ場合に可読性を向上することができます。
long creditNumber = 1234_5678_9012L; // クレジットカードナンバー
他にも16進数、2進数などでも使用できます。
long maxAdress = 0xA0_0C_F9_D1_A2_C1L; byte nybbles = 0b0010_0101; int bytes = 0b11010010_01101001_10010100_10010010;
ただし、「_(アンダースコア)」を挿入する位置には注意が必要です。
先頭の場合は、数値リテラルではなく、変数として認識されるのでNGです。
また末尾もエラーとなります。
その他にも小数点「.」の前後や「0x」接頭辞、「F」や「L」の接尾辞の前後や間に入れることはできません。
// 整数 int a1 = _99; // NG int a2 = 99_; // NG double a3 = 1_.1; // NG double a4 = 1._1; // NG float a5 = 1.1234_F; // NG float a6 = 1.1234F_; // NG int a7 = 0_xF2C3; // NG int a8 = 0x_F2C3; // NG
3. Strings in switch Statements
(switch文のcaseラベルに文字列を使える)
caseラベルに文字列リテラルを使えるようになりました。
private String getSeason(String month) { String season; switch (month) { case "March": case "April": case "May": season = "spring"; break; case "June": case "July": case "November": season = "summer"; break; case "September": case "October": case "August": season = "autumn"; break; case "December": case "January": case "February": season = "wintter"; break; default: throw new IllegalArgumentException("Invalid month : " + month); } return season; }
4. Type Inference for Generic Instance Creation
(コンストラクタ呼び出し時の型推論)
インスタンス生成時の型推論が実装されました。
List<String> list = new ArrayList<String>(); Map<String, List<String>> map = new HashMap<String, List<String>>();
と記述していたものが
List<String> list = new ArrayList<>(); Map<String, List<String>> map = new HashMap<>();
と記述できるようになりました。
「<>」をダイヤモンド演算子と呼びます。
ただし、サポートされているのは限定的です。以下の時は使えません。
// メソッドの引数となる場合 class Sample { private List<String> list; public void setList(List<String> list) { this.list = list; } } Sample sample = new Sample(); sample.setList(new ArrayList<>()); // 型 Sample のメソッド setList(List<String>) は引数 (ArrayList<Object>) に適用できません
// 無名(匿名)クラス List<String> a = new List<>() { // '<>' は匿名クラスでは使用できません @Override public int size() { return 0; } @Override public boolean isEmpty() { return false; } @Override public boolean contains(Object o) { return false; } // 以下省略 }
5. The try-with-resources Statement
(リソース管理用構文の追加)
必ずクローズしなければならないリソースを使う際、try-finally構文を使いますが、Java7からは以下のような記述でリソースのクローズを自動化してくれます。
String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path)) { return br.readLine(); } }
Java7で追加された「AutoCloseable」を実装するとこの機能が使えるようになります。
また、複数リソースを定義することも可能で、finallyを書くこともできます。
しかし、実行される順番には注意が必要です。
public class TheTryWithResourcesStatement { public void execute() throws Exception { try ( Closable1 c1 = new Closable1(); Closable2 c2 = new Closable2(); Closable3 c3 = new Closable3(); ) { System.out.println("something"); } finally { System.out.println("finally"); } } } class Closable1 implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Closable1"); } } class Closable2 implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Closable2"); } } class Closable3 implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Closable3"); } }
■ 実行結果
something
Closable3
Closable2
Closable1
finally
クローズされる順番は定義順の逆になります。このオブジェクト管理はキューではなく、スタックのようなイメージです。
また、finallyの前にクローズ処理が行われるので、ここにも注意が必要です。
6. Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking
(複数のcatch節、例外の再スローについての改善)
複数の例外エラーcatch
複数の例外エラーをcatchできるようになりました。
- Java6
try { DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dbfactory.newDocumentBuilder(); Document doc = builder.parse(new File("helloworld.xml")); Element root = doc.getDocumentElement(); } catch (ParserConfigurationException pcex) { pcex.printStackTrace(); } catch (SAXException saxex) { saxex.printStackTrace(); } catch (IOException ioex) { ioex.printStackTrace(); }
- Java7
try { DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dbfactory.newDocumentBuilder(); Document doc = builder.parse(new File("helloworld.xml")); Element root = doc.getDocumentElement(); } catch (ParserConfigurationException | SAXException | IOException ex) { ex.printStackTrace(); }
例外の再スロー時の型推論
Javaの例外処理ではメソッドで宣言しているエラー(RuntimeExceptionを除く)しかスローできませんでした。 そのため下記コードの場合はコンパイルエラーとなります。 (メソッドでの例外スローはParserConfigurationException, SAXException, IOExceptionに対し、内部でExceptionをスローしているため)public void safeThrow() throws ParserConfigurationException, SAXException, IOException { try { DocumentBuilderFactory dbfactory = DocumentBuilderFactory .newInstance(); DocumentBuilder builder = dbfactory.newDocumentBuilder(); Document doc = builder.parse(new File("helloworld.xml")); Element root = doc.getDocumentElement(); } catch (Exception ex) { // Java6ではコンパイルエラー throw ex; } }
しかし、try句の中で発生するエラーはParserConfigurationException, SAXException, IOExceptionもしくはRuntimeExceptionになります。
この場合catchをExceptionで受けてもその実態は上記のどれかとなるため、Java7では型推論によりExceptionでもスロー可能となります。