Java7の実験。

正式リリースも近いのでいじってみた。
文法上の変更や新しい記法などを中心に、いざソースを読む際にちょっと困ったりしないような視点でみてみました。

AutoCloseable

どうでもいいけど、Closableじゃないんだね。
http://oxforddictionaries.com/noresults?dictionaryVersion=region-uk&isWritersAndEditors=true&noresults=true&page=1&pageSize=20&q=closeable&searchUri=All&sort=alpha&type=dictionarysearch


って該当なしにされるんだけど・・・まぁいいか。
コンパイルは対応していなくてもコードアシストレベルではeclipseが現状でも頑張ってくれるし。



匿名なのでわかりにくいかもしれないけど・・・
try(ここで初期化) {
} catch(Exception e) {
}


といった文法
catchは省略不可っぽい。
(匿名インナークラスの場合throws宣言なしでも不可。インナークラスなんかをちゃんと定義してやれば可能)

   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
         }
       };
     )  {

        //処理

   } catch(Exception e) {
     System.out.println("catch");
   } finally {
     System.out.println("try finally");
   }

結果

ac1 close
try finally


どうやら、finally前でcloseされるようだ。
というわけで、finallyでそのリソースは使用できないようですね。
※catchや、finallyだとそもそもスコープ外。場合によっては中でtry-catchブロックが必要になることもあるかと。


以下のように外側で変数定義だけ済ましておくなんてのはコンパイルエラー

   AutoCloseable ac1 = null;
   try (ac1 = new AutoCloseable() {

     @Override
     public void close() throws Exception {
       System.out.println("ac1 close");
     }
   };)  {
   } catch(Exception e) {
     System.out.println("catch");
   } finally {
     System.out.println("try finally");
   }

ちなみに、以下のようにtryの中での変数への代入に関してもコンパイルエラー
エラー: 自動クローズ可能なリソースac1に値を代入することはできません

   try (AutoCloseable ac1 = null)  {
     ac1 = new AutoCloseable() {
       @Override
       public void close() throws Exception {
         System.out.println("ac1 close");
       }
     };
   } catch(Exception e) {
     System.out.println("catch");
   } finally {
     System.out.println("try finally");
   }


複数のリソース初期化にも対応

   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
         }
       };
       AutoCloseable ac2 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac2 close");
         }
       };
     )  {
   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     System.out.println("try finally");
   }

結果

ac2 close
ac1 close
try finally

だそうで、開いたのと逆に閉じていくという鉄則どおりの挙動ですね。




んじゃまぁ、例外が発生した場合どうなるのか?
両方とも例外が発生した場合

   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
           throw new Exception("close exception");
         }
       };
       AutoCloseable ac2 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac2 close");
           throw new Exception("close exception");
         }
       };
     )  {
   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     System.out.println("try finally");
   }
ac2 close
ac1 close
java.lang.Exception: close exception
       at java7.autoclose.AutoCloseMain$2.close(AutoCloseMain.java:20)
       at java7.autoclose.AutoCloseMain.main(AutoCloseMain.java:24)
       Suppressed: java.lang.Exception: close exception
               at java7.autoclose.AutoCloseMain$1.close(AutoCloseMain.java:12)
               ... 1 more

と、Suppressedが追加されていますね。
最初を主として、その後はsuppressedとして追加されていくようです。
例外が発生しても残りのclose処理はちゃんと実行されていきます。

ThrowableにはaddSuppressedと、getSuppressedが追加されています(protectedのコンストラクタも)
   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
           throw new Exception("close exception");
         }
       };
       AutoCloseable ac2 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac2 close");
           throw new Exception("close exception");
         }
       };
     )  {
   } catch (Exception e) {
     e.printStackTrace();
     System.out.println("ここからgetSuppressed");
     Throwable[] suppressed = e.getSuppressed();
     for (Throwable throwable : suppressed) {
       throwable.printStackTrace();
     }
   } finally {
     System.out.println("try finally");
   }
ac2 close
ac1 close
java.lang.Exception: close exception
       at java7.autoclose.AutoCloseMain$2.close(AutoCloseMain.java:20)
       at java7.autoclose.AutoCloseMain.main(AutoCloseMain.java:24)
       Suppressed: java.lang.Exception: close exception
               at java7.autoclose.AutoCloseMain$1.close(AutoCloseMain.java:12)
               ... 1 more
ここからgetSuppressed
java.lang.Exception: close exception
       at java7.autoclose.AutoCloseMain$1.close(AutoCloseMain.java:12)
       at java7.autoclose.AutoCloseMain.main(AutoCloseMain.java:24)
try finally

マルチキャッチ

マルチキャッチは

} catch (IOException | AssertionError e) {

まさかのパイプ。変数名は最後のみというのがポイント。
てっきりセミコロン区切だと思っていたのに・・・

数値表現

//数値表現に_を入れて、区切を意識させられる
BigDecimal currency = new BigDecimal(123_456_789);
System.out.println(currency);
//123456789

//2進を16進の0xのように、0bで表現可能
int bit = 0b10101;
System.out.println(bit);
//21

ジェネリクスまわり

型推論の進化
基本的には右辺を書いてからアシストで左辺を定義ってコーディングなのでちょっと困るような・・・・

List<String> l = new ArrayList<>();
l.add("test1");
l.add("test2");
for (String string : l) {
        System.out.println(string);
}

JDBC4.1

さて・・・今まで見ないことにされていたRowSetだけど・・・
やはり今回も気にしない方向で、AutoCloseable対応位のつもりでいればいいかも?
http://download.java.net/jdk7/docs/technotes/guides/jdbc/jdbc_41.html

その他

後は細かいクラスやNIOやスレッドまわりは適宜。
switchでStringってのも記述に関しては新しくないので問題ないと思うので
きっとこのあたりだけ押さえておけばひとまずは困らないのかなぁ・・・なんて。