JJUG Cross Community Conference 2012 Fall[R1-1]   今さら Coin,されど Coin                                                       ...
木村 英一 って、誰 ?武蔵小杉駅 横須賀線口の前に立つビルで  Java 案件支援, チューニング                           諸々に対応してます。                                   ...
Project Coin での主な改良ポイント   Switch/case ラベルに文字列リテラル   整数リテラルの拡張記法   1つのcatchで複数例外をキャッチ   ダイヤモンド(<>)     総称インスタンス生成時の型推論...
String in SwitchSwitch/case ラベルに文字列リテラル             © 2012 EIICHI KIMURA. All Rights Reserved.   2012/11/10 13:00-14:00   4
case ラベルに文字列リテラル OKint monthNameToDays(String s, int year) {                                                        switch...
switch/case 文の String 型対応 – ○ なところ◙ “ switch(式)”の 式 に String 型が結果となる式を記述できる◙ case ラベルに “文字列リテラル”(式)を記述できる◙ case ラベルに Strin...
○ case ラベルが文字列リテラル式・定数public class StringInSwitch10 { static final String ss = “s”; public static void main(String[] args)...
Switch/case 文の String 型対応 – × なところ× 式 に String[Buffer | Builder] 型は記述できない× case ラベルに null を記述できない× 式 が null でも default ラベル...
× String[Buffer | Builder] 型は記述できないpublic class StringInSwitch5 { public static void main(String[] args) {  StringBuffer s...
× case ラベルに null を記述できないpublic class StringInSwitch1 { public static void main(String[] args) {  String s = null;  switch(...
× 式が null の時 default ラベルに分岐しないpublic class StringInSwitch2 { public static void main(String[] args) {  String s = null;  s...
× 字面が異なる同じ文字列は記述できないpublic class StringInSwitch {  final static String ss = “¥u3046”; // “う”  public static void main(Stri...
× final でない変数は case に記述できないpublic class StringInSwitch3 { static String ss = "s";public static void main(String[] args) { ...
生成されるバイトコードは 2 つの switch 文にswitch(s) { case "99"     : System.out.println("case 99"); break; case "98"     : System.out.pr...
Binary Integral Literal &  Underscores     in Numeric Literals整数リテラルの拡張記法            © 2012 EIICHI KIMURA. All Rights Rese...
整数リテラルの拡張記法 二進数表現記法 : プリフィックス 0b, 0B 桁区切り ‘_’ 記法 : ‘_’ は複数重ねてもよい。  1346704470 → 1_346_704_470  0x50451456 → 0x5045_145...
2進数リテラル/桁区切り文字 – ○ なところ◙ 2進数表現の整数リテラルは、整数リテラルが 記述できる場所で利用できる◙ 桁区切り文字は、複数 ‘_’ 文字を重ねても よい◙ 桁区切り文字は、整数リテラル、浮動小数 点リテラルで利用できる  ...
○ 2進数表現は整数リテラルの使える場所でclass BinaryLiteral3 { public static void main(String args[]) {  // 2進数表現の整数リテラルをメソッド引数に利用した例  String...
○ 桁区切り文字は複数 ‘_’ 文字を重ねてよいclass BinaryLiteral4 { public static void main(String args[]) {  double d2 = Double.longBitsToDoub...
○ ‘_’は浮動小数点数リテラルにも使えるclass BinaryLiteral5 { public static void main(String args[]) {  double minVd = 0x0.0__0000__0000__00...
2進数リテラル/桁区切り文字 - × なところ× 桁区切り文字を数値の先頭及び末尾には記述でき ない× 桁区切り文字を、浮動小数点数リテラルの指数部開 始文字(e, p等)前後に記述できない× 文字列表現から数値変換するメソッド(例えば Int...
× 桁区切り文字を数値の先頭/末尾におけないclass BinaryLiteral6 {  public static void main(String args[]) {        // リテラルの先頭(接頭子がある場合は、その直後)に置...
× ‘_’を指数部開始文字前後におけないclass BinaryLiteral5 { public static void main(String args[]) {  double minVd = 0x0.0__0000__0000__000...
× 桁区切り文字は文字列数値変換で使えないclass BinaryLiteral7 {  public static void main(String args[]) {    int i = Integer.parseInt("1_000")...
Multi-catch &  More Precise Rethrow1 つの catch で複数例外をキャッチ            © 2012 EIICHI KIMURA. All Rights Reserved.   2012/11/1...
1 つの catch で複数例外をキャッチtry {    // リフレクション操作 : 例えば Class.forName, Class.newInstance,    // Class.getMethod, Method.invoke など...
1 つの catch で複数例外をキャッチ              Xtry {  // リフレクション操作 : 例えば Class.forName, Class.newInstance,  // Class.getMethod, Metho...
複数例外 catch と高精度再スロー - ○ なところ◙ 複数の例外を 1 つの catch 節に ‘|’ で  区切って記述できる◙ ReflectiveOperationException が  利用できる◙ 再スローする例外のクラスを ...
○ 再スローする例外を throws に書けるimport java.io.*;class ExceptionRethrow8 { private static String encode = "S_JIS"; public static vo...
○ ReflectiveOperationException が使える JDK7 では ReflectiveOperationException が導入された。        ClassNotFoundException, IllegalA...
○ ReflectiveOperationException が使える JDK7 では ReflectiveOperationException が導入された。        ClassNotFoundException, IllegalA...
複数例外catchと高精度再スロー – × なところ×複数の例外を ‘|’ で区切って記述する場合、 例外パラメータへの代入はできない×複数の例外を ‘|’ で区切って記述する場合、 親子関係のある例外クラスを両方記述する ことはできない   ...
× 例外パラメータに代入できないvoid test() throws IOException {  InputStreamReader isr = null;  try {      // Data.txt が存在しない場合 FileNotFo...
× 親子関係のある例外を指定できないvoid test() throws IOException { InputStreamReader isr = null; try {    // Data.txt が存在しない場合 FileNotFoun...
例外テーブルで catch 節の実行を制御(1)                            (生成するバイトコード命令列は同じ)① catch(FileNotFoundException | UnsupportedEncodingE...
例外テーブルで catch 節の実行を制御(2)                         (生成するバイトコード命令列は同じ)③ catch(FileNotFoundException e) { }        // Single-C...
Diamond ~ Improved Type Inference for              Generic Instance Creation総称インスタンス生成時の型推論拡張                             ...
総称型クラスのインスタンス生成List list = new ArrayList();                       総称型を使うとList<String> list = new ArrayList<String>();List<...
ダイヤモンド記法 – ○ なところ◙ ジェネリッククラスに対するクラス・インスタンス 生成式(new式)で型引数の記述が省略で きる          © 2012 EIICHI KIMURA. All Rights Reserved.   2...
○ new式で型引数を省略できるpackage java.util;public abstract class AbstractList<E>      extends AbstractCollection<E> implements List...
ダイヤモンド記法 – ▲ なところ▲代入式での変数の型として宣言された型と、 コンパイラによる型推論の結果が同じになると は限らない         © 2012 EIICHI KIMURA. All Rights Reserved.   20...
型推論の結果が直感的でないこともpublic class DiamondTest<T> {  private T value;  public DiamondTest() { }  public DiamondTest(T value) { t...
ダイヤモンド記法 – X なところ×クラス・インスタンス生成式(new式)でのみ利 用可能であり、任意の箇所で型引数を省略 することはできない×New式の型引数が指定され、ジェネリッククラ スの型引数が省略されるとコンパイルできな い     ...
X new式以外では型引数を省略できないimport java.util.*;public class DiamondTest7 { public static void main(String[] args) {  List<List<Str...
型引数の明示的指定時と同じバイトコード “ダイヤモンド” と ”型引数を指定した” 場合と “Raw Type” の場合で、        生成されるバイトコードに違いなし。            ※部分が次のどの場合も、同じバイトコードが...
try-with-resource statement自動リソース管理           © 2012 EIICHI KIMURA. All Rights Reserved.   2012/11/10 13:00-14:00   46
try-with-resources statement                 (自動リソース管理) やっと、リソース解放を明示しなくてもよくなった   finally 節に close 処理を書くことが、守れていない ! 知らな...
try 節の拡張記法 + AutoCloseable の導入 try 節の拡張記法 super interface java.lang.AutoCloseable の導入 finally での close 処理の記述が必要なくなる 例外...
close 処理以外は catch/finally 節に記述する close処理の記述は必要なくなるが、 例外発生の事実は変わらない !    catch 節や throws 句は必須 !!try(InputStream in = new...
リソース対応 try 文 – ○ なところ◙ try-catch-finally のどのブロックにも、明示的 な null チェックと、close() 呼出しとを記述し なくてよい◙ 一つのリソース対応 try 文で、複数のリソース を宣言でき...
ちなみに、コンパイルすると ...(1)try(InputStream in = new FileInputStream(src);    OutputStream out = new FileOutputStream(dest)) { byt...
ちなみに、コンパイルすると ...(2)try {  byte[] buf = new byte[8192];  int n;  while ((n = in.read(buf)) >= 0)    out.write(buf, 0, n); ...
ちなみに、コンパイルすると ...(3)  } catch(final Throwable e3) {                                    In の close 処理を finally で実行。    pe1 ...
addSuppressed()された例外のスタックトレースException @ main :java.lang.RuntimeException : java.io.IOException     at TryWithResource8.te...
リソース対応 try 文 – X なところ×catch, finally ブロックでは明に close() 呼出しできない×close() 以外に必要な後始末処理は省略できない×リソース対応 try 文の宣言した変数に値を代入できない×Auto...
X catch/finally からリソース変数にアクセス不可import java.io.*;import java.sql.*;import javax.sql.*;class TryWithResource6 { void test() ...
X リソース宣言した変数に代入できないimport java.io.*;class TryWithResource5 {                                               Try-with-resour...
X AutoClosable 未実装はリソース宣言できないimport java.io.*;import java.awt.*;class TryWithResource7 {  void test() {    try (SplashScre...
X リソース対応 try ブロック内の宣言は対象外public class TryWithResource9 { public static void main(String args[]) {     TryWithResource9 er ...
X リソース対応 try ブロック内の宣言は対象外class Res9_res implements AutoCloseable {  String name = "[null]";  boolean closed_flag = false; ...
Simplified  Varargs Method Invocation@SafeVarargs アノテーション導入             © 2012 EIICHI KIMURA. All Rights Reserved.   2012/...
Varargs メソッド呼出しの簡素化 @SafeVarargs アノテーションの導入  次の 2 つの警告を抑制する    可変引数メソッド自身の宣言に関する無検査警告    可変引数メソッドのメソッド起動式で無検査警告 コアライブ...
Varargs メソッド呼出しの簡素化 ジェネリッククラスのインスタンスを可変引数として渡されるメソッド、   コンストラクタに対して     呼び出す側(利用者)       無意味なエラーが出力されない     呼び出される側(ライ...
Varargs メソッド呼出しの簡素化 – ○ なところ◙ 可変引数メソッドを利用する立場では、 余分な警告メッセージを気にかけずにすむ◙ ライブラリ開発者の立場では、 余分な警告メッセージに気をつかわせることな く利用してもらえる      ...
○ ジェネリック配列の Varargs の無検査警告import java.util.*;class SafeVarargsTest1 { public static void main(String args[]) {  List<Strin...
Varargs メソッド呼出しの簡素化 – X なところ× @SafeVarargs アノテーションは、 × メソッド/コンストラクタ以外には使えない × 固定引数のメソッド/コンストラクタには使えない × static でも final でも...
X 固定引数メソッドの @SafeVarargs はエラーimport java.util.*;class SafeVarargsTest4 { public static void main(String args[]) {  List<St...
X @SafeVarargs はメソッド警告を抑止しない@SafeVarargs // @SuppressWarnings(“unchecked”)を指定すると警告は出ず、実行時エラーの可能性ありstatic void copyAll(List...
まとめ各々 できること・できないことがある  Switch/case ラベルに文字列リテラル       整数リテラルの拡張記法   1つのcatchで複数例外をキャッチ          ダイヤモンド(<>)         リソース対応 t...
© 2012 EIICHI KIMURA. All Rights Reserved.   2012/11/10 13:00-14:00   70
Upcoming SlideShare
Loading in …5
×

(R1-1) いまさら Coin, されど Coin @ JJUG CCC 2012 Fall

1,706 views

Published on

JJUG CCC 2012 Fall, R1-1 いまさら Coin, されど Coin のスライドです。

This Presentation Slide is the session about PJ Coin at JJUG Cross Community Conference 2012 Fall(Tokyo/Japan), 2012/11/10, The Bellesalle Mita

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,706
On SlideShare
0
From Embeds
0
Number of Embeds
35
Actions
Shares
0
Downloads
13
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

(R1-1) いまさら Coin, されど Coin @ JJUG CCC 2012 Fall

  1. 1. JJUG Cross Community Conference 2012 Fall[R1-1] 今さら Coin,されど Coin (#jjug_r11) 2012/11/10 木村英一 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 1
  2. 2. 木村 英一 って、誰 ?武蔵小杉駅 横須賀線口の前に立つビルで Java 案件支援, チューニング 諸々に対応してます。 Twitter : @kimuchi583 URL : http://kimuchi583.at.webry.info/ http://blog.kimu2.jp/ © 2012 EIICHI KIMURA All Rights Reserved. 2012/11/9 2
  3. 3. Project Coin での主な改良ポイント Switch/case ラベルに文字列リテラル 整数リテラルの拡張記法 1つのcatchで複数例外をキャッチ ダイヤモンド(<>)  総称インスタンス生成時の型推論拡張 リソース対応 try 文 - 自動リソース管理 @SafeVarargs アノテーション導入 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 3
  4. 4. String in SwitchSwitch/case ラベルに文字列リテラル © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 4
  5. 5. case ラベルに文字列リテラル OKint monthNameToDays(String s, int year) { switch(s) { if(s.equals("April") || case "April": s.equals("June") || case "June": s.equals("September") || case "September": s.equals("November")) case "November": return 30; return 30; if(s.equals("January") || case "January": s.equals("March") || case "March": s.equals("May") || case "May": s.equals("July") || case "July": s.equals(“August”) || case "August": s.equals("December")) case "December": return 31; return 31; if(s.equals("February")) case "February": ... ... else default ... ... } }} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 5
  6. 6. switch/case 文の String 型対応 – ○ なところ◙ “ switch(式)”の 式 に String 型が結果となる式を記述できる◙ case ラベルに “文字列リテラル”(式)を記述できる◙ case ラベルに String の定数(final)変数を記述できる © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 6
  7. 7. ○ case ラベルが文字列リテラル式・定数public class StringInSwitch10 { static final String ss = “s”; public static void main(String[] args) { String s = "Hello JDK7"; switch(s) { case "Hello" + " " + "JDK7" : // 文字列リテラルの連結 System.out.println("Match case label :" + "¥"Hello¥" + ¥" ¥" + ¥"JDK7¥""); break; case ss : // ss は static final 修飾された定数 System.out.println(“Match case lable : ss”); break; default : System.out.println("Match default label"); break; } }} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 7
  8. 8. Switch/case 文の String 型対応 – × なところ× 式 に String[Buffer | Builder] 型は記述できない× case ラベルに null を記述できない× 式 が null でも default ラベルに分岐しない× 異なる字面でも、同じ文字列を表す文字列リテ ラルは、同一 switch 文の case ラベルに記述で きない× case ラベルに String 変数は記述できない× 大文字小文字を無視した比較はしない © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 8
  9. 9. × String[Buffer | Builder] 型は記述できないpublic class StringInSwitch5 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("s"); switch(sb) { // sb は StringBuffer なのでコンパイルエラーとなる case "s" : System.out.println("Match case label : ¥"s¥""); break; default : System.out.println("Match default label"); break; } }} StringInSwitch5.java:5: エラー: 互換性のない型 switch(sb) { // sb は StringBuffer なのでコンパイルエラーとなる ^ 期待値: int 検出値: StringBuffer © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 9
  10. 10. × case ラベルに null を記述できないpublic class StringInSwitch1 { public static void main(String[] args) { String s = null; switch(s) { case null : // コンパイルエラーとなる System.out.println("Match case label : null"); break; case "s" : System.out.println("Match case label : ¥"s¥""); break; default : System.out.println("Match default label"); break; } } StringInSwitch1.java:6: エラー: 定数の文字列式が必要です} case null : // コンパイルエラーとなる ^ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 10
  11. 11. × 式が null の時 default ラベルに分岐しないpublic class StringInSwitch2 { public static void main(String[] args) { String s = null; switch(s) { // s が null なので実行時エラー(NPE)発生 // case null : // System.out.println("Match case label : null"); // break; case "s" : System.out.println("Match case label : ¥"s¥""); break; default : System.out.println("Match default label"); break; } } コンパイルはできるが、実行時にエラーとなる。} Exception in thread "main" java.lang.NullPointerException at StringInSwitch2.main(StringInSwitch2.java:5) © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 11
  12. 12. × 字面が異なる同じ文字列は記述できないpublic class StringInSwitch { final static String ss = “¥u3046”; // “う” public static void main(String... args) { switch(args[0]) { case "あ“ : System.out.println("あ"); break; case "い“ : System.out.println("い"); break; case “う” : System.out.println(“う”); break; case "え" : System.out.println("え"); break; case "お" : System.out.println("お"); break; case ss : System.out.println(ss); break; default : System.out.println("default"); break; } }} >javac StringInSwitch.java StringInSwitch.java:11: エラー: caseラベルが重複しています case ss : System.out.println(ss); break; ^ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 12
  13. 13. × final でない変数は case に記述できないpublic class StringInSwitch3 { static String ss = "s";public static void main(String[] args) { String s = "s"; switch(s) { case ss : // ss は final でないので、コンパイルエラーとなる System.out.println("Match case label : ss"); break; default : System.out.println("Match default label"); break; } } StringInSwitch3.java:8: エラー: 定数の文字列式が必要です} case ss : // ss は final でないので、コンパイルエラーとなる ^ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 13
  14. 14. 生成されるバイトコードは 2 つの switch 文にswitch(s) { case "99" : System.out.println("case 99"); break; case "98" : System.out.println("case 98"); break; case "¥u0720" : System.out.println("case ¥u0720"); break;} コンパイルして得られたバイトコードString tmp_s = s; に対応するソースコードイメージint caselable = -1;switch(tmp_s.hashCode()) { case 1834 : // 1834 == "99".hashCode() == "¥u0720".hashCode() 1つ目の switch 文は、 if(tmp_s.equals(“¥u720”)) caselable = 2; else if(tmp_s.equals("99")) caselable = 0; hashCode 値で分岐する break; 2つ目の switch 文で使う case 1833 : // 1537 == "98".hashCode() if(tmp_s.equals("98")) caselable = 1; caselabel の値を求める break; hash値が同じ場合 if 文で文字列比較}switch(caselable) { 2つ目の Switch 文は、 case 0 : System.out.println(“case 99”); break; 1つ目の switch 文で case 1 : System.out.println(“case 98”); break; 求めた caselabel で case 2 : System.out.println("case ¥u0720"); break;} 分岐する switch文 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 14
  15. 15. Binary Integral Literal & Underscores in Numeric Literals整数リテラルの拡張記法 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 15
  16. 16. 整数リテラルの拡張記法 二進数表現記法 : プリフィックス 0b, 0B 桁区切り ‘_’ 記法 : ‘_’ は複数重ねてもよい。  1346704470 → 1_346_704_470  0x50451456 → 0x5045_1456 → 0x50_45_14_56  0b01010000010001010001010001010110 → 0b0101_0000_0100_0101_0001_0100_0101_0110 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 16
  17. 17. 2進数リテラル/桁区切り文字 – ○ なところ◙ 2進数表現の整数リテラルは、整数リテラルが 記述できる場所で利用できる◙ 桁区切り文字は、複数 ‘_’ 文字を重ねても よい◙ 桁区切り文字は、整数リテラル、浮動小数 点リテラルで利用できる © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 17
  18. 18. ○ 2進数表現は整数リテラルの使える場所でclass BinaryLiteral3 { public static void main(String args[]) { // 2進数表現の整数リテラルをメソッド引数に利用した例 String s2 = Integer.toString(0b1111101000, 2); String s8 = Integer.toString(0b1111101000, 8); String s10 = Integer.toString(0b1111101000, 10); String s16 = Integer.toString(0b1111101000, 16); System.out.format(" 2進数表現 = %s¥n", s2); System.out.format(" 8進数表現 = %s¥n", s8); System.out.format("10進数表現 = %s¥n", s10); System.out.format("16進数表現 = %s¥n", s16); }} 02進数表現 = 1111101000 08進数表現 = 1750 10進数表現 = 1000 16進数表現 = 3e8 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 18
  19. 19. ○ 桁区切り文字は複数 ‘_’ 文字を重ねてよいclass BinaryLiteral4 { public static void main(String args[]) { double d2 = Double.longBitsToDouble( 注) 表示の都合上の改行 0B0100_0000_0000_1001_0010_0001_1111_1011 ¥¥ _0101_0100_0100_0100_0010_1101_0001_1000L); double d16 = Double.longBitsToDouble( 0x4009___21FB__5444_2D18L); System.out.format("d16 = %2$e¥n", d16); }} d2 = 3.141593e+00, d16 = 3.141593e+00 桁区切り文字 ‘_’ を重ねる文字数を変えてもよい。 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 19
  20. 20. ○ ‘_’は浮動小数点数リテラルにも使えるclass BinaryLiteral5 { public static void main(String args[]) { double minVd = 0x0.0__0000__0000__0001P-1_022; // 2^(-1074) = Double.MIN_VALUE double pI = 3.141592653589793; // Math.PI float maxVf = 3.4028__2346__6385__2886E38f; // Float.MAX_VALUE String minVds = Double.toString(minVd); 0x0.1 = 16-1= 2-4 String pIs = Double.toString(pI); 0x0.01 = 16-2=2-8 String maxVfs = Float.toString(maxVf); … System.out.format("min_value = %s¥n", minVds); System.out.format("pi = %s¥n", pIs); System.out.format("max_value = %s¥n", maxVfs); }} min_value = 4.9E-324 pi = 3.141592653589793 max_value = 3.4028235E38 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 20
  21. 21. 2進数リテラル/桁区切り文字 - × なところ× 桁区切り文字を数値の先頭及び末尾には記述でき ない× 桁区切り文字を、浮動小数点数リテラルの指数部開 始文字(e, p等)前後に記述できない× 文字列表現から数値変換するメソッド(例えば Integer#parseInt(String)など)の String 型の引数 中に桁区切り文字を含んだ数値表現は記述できない © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 21
  22. 22. × 桁区切り文字を数値の先頭/末尾におけないclass BinaryLiteral6 { public static void main(String args[]) { // リテラルの先頭(接頭子がある場合は、その直後)に置いてみた int d2s = 0b_11_0000_0011_1001; int d8s = 0_30_071; // これは OK !! int d10s = _12_345; // これは変数扱い !! int d16s = 0x_3039; // リテラルの末尾に _ を置いてみた int d2t = 0b11_0000_0011_1001_; int d8t = 030_071_; int d10t = 12_345_; int d16t = 0x3039_; }} BinaryLiteral6.java:4: エラー: 不正なアンダースコアです int d2s = 0b_11_0000_0011_1001; ^ … © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 22
  23. 23. × ‘_’を指数部開始文字前後におけないclass BinaryLiteral5 { public static void main(String args[]) { double minVd = 0x0.0__0000__0000__0001_P-1_022; // 2^(-1074) = Double.MIN_VALUE, p の直前に _ を置く double pI = 3.1415_9265__3589___793; // Math.PI float maxVf = 3.4028__2346__6385__2886E_38f; // Float.MAX_VALUE, e の直後に ‘_’ を置く String minVds = Double.toString(minVd); String pIs = Double.toString(pI); String maxVfs = Float.toString(maxVf); System.out.format("min_value = %s¥n", minVds); System.out.format("pi = %s¥n", pIs); System.out.format("max_value = %s¥n", maxVfs); } BinaryLiteral5.java:3: エラー: 不正なアンダースコアです} double minVd = 0x0.0__0000__0000__0001_P-1_022 ; ^ BinaryLiteral5.java:6: エラー: 不正なアンダースコアです float maxVf = 3.4028__2346__6385__2886E_38f; ^ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 23
  24. 24. × 桁区切り文字は文字列数値変換で使えないclass BinaryLiteral7 { public static void main(String args[]) { int i = Integer.parseInt("1_000"); System.out.format("i = %d¥n", i); }}コンパイルはできますが、実行時にエラーとなります。Exception in thread "main“ ¥ java.lang.NumberFormatException: For input string: "1_000“ at java.lang.NumberFormatException.forInputString( ¥ NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:492) at java.lang.Integer.parseInt(Integer.java:527) at BinaryLiteral7.main(BinaryLiteral7.java:3) © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 24
  25. 25. Multi-catch & More Precise Rethrow1 つの catch で複数例外をキャッチ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 25
  26. 26. 1 つの catch で複数例外をキャッチtry { // リフレクション操作 : 例えば Class.forName, Class.newInstance, // Class.getMethod, Method.invoke などの呼出し処理}catch(ClassNotFoundException cnfe) { log(cnfe); throw cnfe;}catch(InstantiationException ie) { log(ie); throw ie;}catch(NoSuchMethodException nsme) { log(nsme); throw nsme;}catch(InvocationTargetException ite) { log(ite); throw ite;} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 26
  27. 27. 1 つの catch で複数例外をキャッチ Xtry { // リフレクション操作 : 例えば Class.forName, Class.newInstance, // Class.getMethod, Method.invoke などの呼出し処理}catch(Exception e) { log(e); throw e; 従来のサボリ方 ... 当然、推奨しません !!}try { // リフレクション操作 : 例えば Class.forName, Class.newInstance, // Class.getMethod, Method.invoke などの呼出し処理} catch(ClassNotFoundException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { log(e); throw e;} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 27
  28. 28. 複数例外 catch と高精度再スロー - ○ なところ◙ 複数の例外を 1 つの catch 節に ‘|’ で 区切って記述できる◙ ReflectiveOperationException が 利用できる◙ 再スローする例外のクラスを throws 句の例 外宣言に記述できる © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 28
  29. 29. ○ 再スローする例外を throws に書けるimport java.io.*;class ExceptionRethrow8 { private static String encode = "S_JIS"; public static void main(String args[]) { ExceptionRethrow8 er = new ExceptionRethrow8(); try { er.test(); } catch(FileNotFoundException | UnsupportedEncodingException e) { System.out.println("@ main multi catch : "); e.printStackTrace(); };}void test() throws FileNotFoundException, UnsupportedEncodingException { InputStreamReader isr = null; try { // Data.txt が存在しない場合 FileNotFoundException が発生する // encodeで指定された文字セットが未サポートの場合 UnsupportedEncodingException が発生する isr = new InputStreamReader(new FileInputStream("Data.txt"), encode); } catch(Exception e) { System.out.println("Exception @ test - catch : "); e.printStackTrace(); throw e; } finally { try { if(isr != null) isr.close(); } catch(IOException e) { System.out.println("Exception @ test - finally: " + e); } } } Exception で catch し再スローする時、} JDK6 では throws に Exception と記述する必要がある(さもないとコンパイル時エラー) JDK7 では 実際に throw される例外(または、その親クラス)を throws に書ける。 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 29
  30. 30. ○ ReflectiveOperationException が使える JDK7 では ReflectiveOperationException が導入された。  ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException の親クラスtry { // リフレクション操作 : 例えば Class.forName, Class.newInstance, // Class.getMethod, Method.invoke などの呼出し処理} catch(ClassNotFoundException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { log(e); throw e;} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 30
  31. 31. ○ ReflectiveOperationException が使える JDK7 では ReflectiveOperationException が導入された。  ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException の親クラスtry { // リフレクション操作 : 例えば Class.forName, Class.newInstance, // Class.getMethod, Method.invoke などの呼出し処理} catch(ReflectiveOperationException e) { log(e); throw e;} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 31
  32. 32. 複数例外catchと高精度再スロー – × なところ×複数の例外を ‘|’ で区切って記述する場合、 例外パラメータへの代入はできない×複数の例外を ‘|’ で区切って記述する場合、 親子関係のある例外クラスを両方記述する ことはできない © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 32
  33. 33. × 例外パラメータに代入できないvoid test() throws IOException { InputStreamReader isr = null; try { // Data.txt が存在しない場合 FileNotFoundException が発生する // encode で指定された文字セットがサポートされていない場合 // UnsupportedEncodingException が発生する isr = new InputStreamReader(new FileInputStream("Data.txt"), encode); } catch(FileNotFoundException | UnsupportedEncodingException e) { System.out.println("Exception @ test - catch : "); e.printStackTrace(); e = new IOException(e); // コンパイルエラー throw e; } finally { try { if(isr != null) isr.close(); } catch(IOException e) { System.out.println("Exception @ test - finally: " + e); } ExceptionRethrow5.java:19:エラー: } 複数catchパラメータeに値を代入することはできません} e = new IOException(e); // コンパイル時にエラーとなる ^複数の例外をキャッチする catch 節の例外パラメータは暗黙に final !!つまり、そのパラメータに代入できない !! © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 33
  34. 34. × 親子関係のある例外を指定できないvoid test() throws IOException { InputStreamReader isr = null; try { // Data.txt が存在しない場合 FileNotFoundException が発生する // encode で指定された文字セットがサポートされていない場合 // UnsupportedEncodingException が発生する isr = new InputStreamReader(new FileInputStream("Data.txt"), encode); } catch( FileNotFoundException | UnsupportedEncodingException | IOException e) { System.out.println("Exception @ test - catch : "); e.printStackTrace(); throw e; } finally { try { if(isr != null) isr.close(); } catch(IOException e) { System.out.println("Exception @ test - finally: " + e); } }} ExceptionRethrow10.java:16:エラー: 複数catch文の代替をサブクラス化によって関連付けることはできません } catch(FileNotFoundException | UnsupportedEncodingException | IOException e) { ^ 代替FileNotFoundExceptionは代替IOExceptionのサブクラスです親子関係にある例外クラスを、複数の例外をキャッチする catch 節に指定するとコンパイルエラーとなる。 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 34
  35. 35. 例外テーブルで catch 節の実行を制御(1) (生成するバイトコード命令列は同じ)① catch(FileNotFoundException | UnsupportedEncodingException e) // Multi-Catch 例外テーブル void test() throws java.io.IOException; に違いあり Code: 0: aconst_null … バイトコード命令列は同じ Exception table: from to target type 22 30 33 Class java/io/IOException 2 22 41 Class java/io/FileNotFoundException 2 22 41 Class java/io/UnsupportedEncodingException 2 22 48 any 49 57 60 Class java/io/IOException 41 49 48 any② catch(IOException e) // Single-Catch w/親クラス - JDK6以前でも有効なコードの場合(1) 例外テーブル void test() throws java.io.IOException; に違いあり Code: 0: aconst_null … バイトコード命令列は同じ Exception table: from to target type 22 30 33 Class java/io/IOException 2 22 41 Class java/io/IOException 2 22 48 any 49 57 60 Class java/io/IOException 41 49 48 any © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 35
  36. 36. 例外テーブルで catch 節の実行を制御(2) (生成するバイトコード命令列は同じ)③ catch(FileNotFoundException e) { } // Single-Catchを2つ③ catch(UnsupportedEncodingException e) { } // JDK6以前でも有効なコードの場合(2) 例外テーブル void test() throws java.io.IOException; に違いあり Code: 0: aconst_null … バイトコード命令列も膨らむ Exception table: from to target type 22 30 33 Class java/io/IOException 2 22 41 Class java/io/FileNotFoundException 2 22 48 Class java/io/UnsupportedEncodingException 2 22 55 any 49 57 67 Class java/io/IOException 41 49 55 any © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 36
  37. 37. Diamond ~ Improved Type Inference for Generic Instance Creation総称インスタンス生成時の型推論拡張 Pag © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 e 37
  38. 38. 総称型クラスのインスタンス生成List list = new ArrayList(); 総称型を使うとList<String> list = new ArrayList<String>();List<List<List<List<List<String>>>>> list = new ArrayList<List<List<List<List<String>>>>>(); 型引数宣言を2度書くのは面倒だ !! ダイヤモンドを使って、楽しようList<String> list = new ArrayList<>();List<List<List<List<List<String>>>>> list = new ArrayList<>(); © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 38
  39. 39. ダイヤモンド記法 – ○ なところ◙ ジェネリッククラスに対するクラス・インスタンス 生成式(new式)で型引数の記述が省略で きる © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 39
  40. 40. ○ new式で型引数を省略できるpackage java.util;public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // ... public List<E> subList(int fromIndex, int toIndex) { return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex)); } // ...} JDK 7 の java.util.AbstractList クラスの subList(int, int)メソッドのソースで、すでに利用している。JDK6 u23 のソースでは <E> になっている。public List<E> subList(int fromIndex, int toIndex) { return (this instanceof RandomAccess ? new RandomAccessSubList<E>(this, fromIndex, toIndex) : new SubList<E>(this, fromIndex, toIndex)); } © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 40
  41. 41. ダイヤモンド記法 – ▲ なところ▲代入式での変数の型として宣言された型と、 コンパイラによる型推論の結果が同じになると は限らない © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 41
  42. 42. 型推論の結果が直感的でないこともpublic class DiamondTest<T> { private T value; public DiamondTest() { } public DiamondTest(T value) { this.value = value; } public T getValue() { return value; } public static void main(String[] args) { DiamondTest<Number> b1 = new DiamondTest<>(); DiamondTest<Number> b2 = new DiamondTest<>(1); System.out.format( "b1=%1$d, b2=%2$d¥n", b1.getValue(), b2.getValue()); }} > DiamondTest.java DiamondTest.java:9: エラー: 互換性のない型 DiamondTest<Number> b2 = new DiamondTest<>(1); ^ 期待値: DiamondTest<Number> 検出値: DiamondTest<Integer> © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 42
  43. 43. ダイヤモンド記法 – X なところ×クラス・インスタンス生成式(new式)でのみ利 用可能であり、任意の箇所で型引数を省略 することはできない×New式の型引数が指定され、ジェネリッククラ スの型引数が省略されるとコンパイルできな い © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 43
  44. 44. X new式以外では型引数を省略できないimport java.util.*;public class DiamondTest7 { public static void main(String[] args) { List<List<String>> lls = new ArrayList<>(3); ArrayList<String> als = new ArrayList<>(); als.add("1"); als.add("22"); als.add("333"); als.add("4444"); als.add("55555"); // new 式であるが lls.add(new ArrayList<Object>()) と推論するのでコンパイルエラー // lls.add(new ArrayList<>()); lls.add(new ArrayList<String>()); lls.add(new ArrayList<String>()); lls.add(als); // コンパイルエラー, (ArrayList<String>) でキャストすると OK ArrayList<String> ls = (ArrayList<>)(lls.get(2)); String s = ls.get(4); System.out.println("s = " + s); // s == "55555" }} DiamondTest7.java:15:エラー: 式の開始が不正です ArrayList ls = (ArrayList<>)(lls.get(2)); ^ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 44
  45. 45. 型引数の明示的指定時と同じバイトコード “ダイヤモンド” と ”型引数を指定した” 場合と “Raw Type” の場合で、 生成されるバイトコードに違いなし。  ※部分が次のどの場合も、同じバイトコードが生成される。import java.util.*;class DiamondTest1 { public static void main(String[] args) { ※ ArrayList[______] arg_list = new ArrayList[_____](args.length); for(String s : args) { arg_list.add(s); } System.out.println("arg_list = " + arg_list); }}ArrayList<String> arg_list = new ArrayList< >(args.length);ArrayList<String> arg_list = new ArrayList<String>(args.length);ArrayList arg_list = new ArrayList (args.length); © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 45
  46. 46. try-with-resource statement自動リソース管理 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 46
  47. 47. try-with-resources statement (自動リソース管理) やっと、リソース解放を明示しなくてもよくなった  finally 節に close 処理を書くことが、守れていない ! 知らないし ...  さらに、例外発生個所によっては、その記述も面倒だった !!InputStream in = new FileInputStream(src);try { OutputStream out = new FileOutputStream(dest) ; try { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); // ここで例外が発生し、 } finally { out.close(); // ここでも例外が発生し、 }} finally { in.close(); // さらに、ここでも例外が発生するかも} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 47
  48. 48. try 節の拡張記法 + AutoCloseable の導入 try 節の拡張記法 super interface java.lang.AutoCloseable の導入 finally での close 処理の記述が必要なくなる 例外発生中での別の例外発生時の処理の記述も必要なし try(InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 48
  49. 49. close 処理以外は catch/finally 節に記述する close処理の記述は必要なくなるが、 例外発生の事実は変わらない !  catch 節や throws 句は必須 !!try(InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) { // ...} catch(IOExcption e) { /* 例外発生時の処理を記述する */}public void exec() throws IOException { OR try(InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) { // ... }} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 49
  50. 50. リソース対応 try 文 – ○ なところ◙ try-catch-finally のどのブロックにも、明示的 な null チェックと、close() 呼出しとを記述し なくてよい◙ 一つのリソース対応 try 文で、複数のリソース を宣言できる◙ 例外ハンドラ内での例外発生時にも適切に 処理される © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 50
  51. 51. ちなみに、コンパイルすると ...(1)try(InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8192]; 複数のリソースを宣言できる int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); In, out の null チェックのコードと、} catch(IOExcption e) { close の呼出しは書かないでよい /* 例外発生時の処理を記述する */} コンパイルして得られたバイトコード に対応するソースコードイメージtry { InputStream in = new FileInputStream(src); Throwable pe1 = null; try { OutputStream out = new FileOutputStream(dest); Throwable pe2 = null; © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 51
  52. 52. ちなみに、コンパイルすると ...(2)try { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); out の close 処理を finally で実行。 } catch(final Throwable e1) { out の null チェックと、 pe2 = e1; throw e1; close の際に例外発生した場合、 } finally { 先に発生した例外の中に取り込む。 if(out != null) { そして、上位にスローされるのはあくまで if(pe2 != null) { も最初の例外である。 try { out.close(); } catch(Throwable e2) { pe2.addSuppressed(e2); } } else { out.close(); } } } © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 52
  53. 53. ちなみに、コンパイルすると ...(3) } catch(final Throwable e3) { In の close 処理を finally で実行。 pe1 = e3; in の null チェックと、 throw e3; close の際に例外発生した場合、 } finally { 先に発生した例外の中に取り込む。 if(in != null) { そして、上位にスローされるのはあくまで if(pe1 != null) { も最初の例外である。 try { in.close(); } catch(Throwable e4) { pe1.addSuppressed(e4); } } else { in.close(); } } }} catch(IOException e) { /* 例外発生時の処理を記述する */} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 53
  54. 54. addSuppressed()された例外のスタックトレースException @ main :java.lang.RuntimeException : java.io.IOException at TryWithResource8.test(TryWithResource8.java:39) at TryWithResource8.main(TryWithResource8.java:20) ①Caused by: java.io.IOException at TryWithResource8.test(TryWithResource8.java:35) ... 1 more ② Suppressed: java.lang.AssertionError at TryWithResource8_resource.close(TryWithResource8.java:11) at TryWithResource8.test(TryWithResource8.java:36) ③ ... 1 more catch(IOException ex) { // ② Throwable pex = ex; pex.addSuppressed(new AssertionError()); // ③ throw new RuntimeException(ex); // ① } © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 54
  55. 55. リソース対応 try 文 – X なところ×catch, finally ブロックでは明に close() 呼出しできない×close() 以外に必要な後始末処理は省略できない×リソース対応 try 文の宣言した変数に値を代入できない×AutoClosable ではないクラスはリソース宣言できない×try ブロック内で宣言したリソースはclose()を呼出さない © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 55
  56. 56. X catch/finally からリソース変数にアクセス不可import java.io.*;import java.sql.*;import javax.sql.*;class TryWithResource6 { void test() { int n = 1; // プレースホルダーインデックス String str = "column1"; // プレースホルダ置換え文字列 try (Connection con = DriverManager.getConnection(url, usr, pwd); PreparedStatement ps = con.prepareStatement(“…")) { con.setAutoCommit(false); ps.setString(n, str); // n 番目のプレースホルダに str を指定 int res = ps.executeUpdaet(); // ... con.commit(); } catch (SQLException ex) { if(con != null) // con はスコープ外なのでコンパイル時のエラーとなる con.rollbak(); // con はスコープ外なのでコンパイル時のエラーとなる ex.printStackTrace(); } }} このような場合は、通常の try-catch-finally を使う © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 56
  57. 57. X リソース宣言した変数に代入できないimport java.io.*;class TryWithResource5 { Try-with-resource 文で void test() { 宣言されたリソースの String str = null; 変数は final となる。 try(BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream("Data.txt"), "SJIS"))) { while((str = br.readLine()) != null) System.out.println(str); br = new BufferedReader( new InputStreamReader( new FileInputStream(“AnotherData.txt”, “SJIS”)); } }}TryWithResource8.java:15: エラー :自動クローズ可能なリソースbrに値を代入することはできません br = new BufferedReader(new InputStreamReader( ¥ new FileInputStream("AnotherData.txt"), “SJIS”)); ^ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 57
  58. 58. X AutoClosable 未実装はリソース宣言できないimport java.io.*;import java.awt.*;class TryWithResource7 { void test() { try (SplashScreen sps = SplashScreen.getSplashScreen()) { // ... } }}TryWithResource7.java:6: エラー: try-with-resourceは変数型に適用されません try (SplashScreen sps = SplashScreen.getSplashScreen()) { ^ 期待値: AutoCloseable検出値: SplashScreen close メソッドがあるクラスのインスタンスなら何でもよい… わけではない。 AutoCloseable インタフェースの実装クラスのインスタンスでなければならない。 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 58
  59. 59. X リソース対応 try ブロック内の宣言は対象外public class TryWithResource9 { public static void main(String args[]) { TryWithResource9 er = new TryWithResource9(); er.test(); } void test() { Res9_res r11 = null; Res9_res r12 = null; try (Res9_res r1 = new Res9_res ("[Resource_1]");) { Res9_res r2 = new Res9_res ("[Resource_2]"); r11 = r1; // finally で確認できるようにスコープの広い変数に代入 r12 = r2; // finally で確認できるようにスコープの広い変数に代入 } finally { System.out.println(); // スコープの広い変数(r11, r12)で状態を確認する System.out.println(r11.getName() + " is " + (r11.isClosed() ? " CLOSED" : "NOT CLOSED !!")); System.out.println(r12.getName() + " is " + (r12.isClosed() ? " CLOSED" : "NOT CLOSED !!")); } }} © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 59
  60. 60. X リソース対応 try ブロック内の宣言は対象外class Res9_res implements AutoCloseable { String name = "[null]"; boolean closed_flag = false; public Res9_res (String str) { name = str; }; public void close() { closed_flag = true; System.out.println(name + " is closed NOW !!"); } public boolean isClosed() { return closed_flag; } public String getName() { return name; }}[Resource_1] is closed NOW !! // r1 の close が呼び出された // r2 の close は呼び出されない[Resource_1] is CLOSED // r1 は close されている[Resource_2] is NOT CLOSED !! // r2 は close されていない © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 60
  61. 61. Simplified Varargs Method Invocation@SafeVarargs アノテーション導入 © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 61
  62. 62. Varargs メソッド呼出しの簡素化 @SafeVarargs アノテーションの導入  次の 2 つの警告を抑制する  可変引数メソッド自身の宣言に関する無検査警告  可変引数メソッドのメソッド起動式で無検査警告 コアライブラリで利用 - 無意味な警告を抑制する  JDK7 の次のメソッドで @SafeVarargs が利用されている  public static <T> List<T> java.util.Arrays.asList(T... a)  public static <T> boolean java.util.Collections.addAll(Collection<? super T> c, T... elements)  public static <E extends Enum<E>> java.util.EnumSet<E> EnumSet.of(E first, E... rest)  protected final void javax.swing.SwingWorker.publish(V... chunks) © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 62
  63. 63. Varargs メソッド呼出しの簡素化 ジェネリッククラスのインスタンスを可変引数として渡されるメソッド、 コンストラクタに対して  呼び出す側(利用者)  無意味なエラーが出力されない  呼び出される側(ライブラリ開発者)  利用者に余分な警告メッセージを提示しないようにできる より複雑な型での可変引数メソッドに効果あり// Sting の List - JDK6 でも警告メッセージは出力されないList<String> ls = Arrays.asList( "", "1", "22", "333", "4444", "55555", "666666", "7777777", "88888888", "999999999“);// String の List の List - JDK6では警告メッセージが出力されていた, JDK7 では警告なしList<List<String>> lls = Arrays.asList( Arrays.asList("", "1", "22", "333", "4444"), Arrays.asList("55555", "666666", "7777777", "88888888", "999999999")); © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 63
  64. 64. Varargs メソッド呼出しの簡素化 – ○ なところ◙ 可変引数メソッドを利用する立場では、 余分な警告メッセージを気にかけずにすむ◙ ライブラリ開発者の立場では、 余分な警告メッセージに気をつかわせることな く利用してもらえる © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 64
  65. 65. ○ ジェネリック配列の Varargs の無検査警告import java.util.*;class SafeVarargsTest1 { public static void main(String args[]) { List<String> l1 = new ArrayList<String>(); Collections.addAll( l1, "", "1", "22", "333", "4444", "55555", "666666", "7777777", "88888888", "999999999"); List<String> l2 = new ArrayList<String>(); List<String> l3 = new ArrayList<String>(); copyAll(l1, l2, l3); 利用側 System.out.println(“l1 = ” + l1); ...} // @SafeVarargs ライブラリ提供側 : JDK7 でコメントをはずすと2つの警告が抑制される static void copyAll(List<String> from, List<String>... tos) { // from → tos[0]...tos[n] に要素をコピーする for(List<String> ls : tos) { ls.addAll(from); } }} > javac -Xlint:unchecked SafeVarargsTest1.java SafeVarargsTest1.java:9: 警告: [unchecked] 型List<String>[]の可変引数パラメータに対する総称型配列の無検査作成です copyAll(l1, l2, l3); ^ JDK6 でのコンパイル結果 SafeVarargsTest1.java:16: 警告: [unchecked] パラメータ化された可変引数型List<String>からのヒープ汚染の可能性があります static void copyAll(List<String> from, List<String>... tos) { ^ JDK7 でのコンパイル結果(@SafeVarargs がない場合) © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 65
  66. 66. Varargs メソッド呼出しの簡素化 – X なところ× @SafeVarargs アノテーションは、 × メソッド/コンストラクタ以外には使えない × 固定引数のメソッド/コンストラクタには使えない × static でも final でもない可変引数メソッドには使えない× メソッド/コンストラクタ本体内のコードに対する警告を抑 制しない © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 66
  67. 67. X 固定引数メソッドの @SafeVarargs はエラーimport java.util.*;class SafeVarargsTest4 { public static void main(String args[]) { List<String> l1 = new ArrayList<String>(); Collections.addAll(l1, "", "1", "22", "333", "4444", "55555"); List<String> l2 = new ArrayList<String>(); listcopy(l1, l2); System.out.println("l1 = " + l1); System.out.println("l2 = " + l2); } @SafeVarargs static void listCopy(List<String> from, List<String> tos) { for(String s : from) { tos.add(s); } }} SafeVarargsTest4.java:14: エラー: SafeVarargs 注釈が無効です。 メソッドlistCopy(List<String>,List<String>)は可変引数メソッドではありません。 static void listCopy(List<String> from, List<String> tos) { ^ © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 67
  68. 68. X @SafeVarargs はメソッド警告を抑止しない@SafeVarargs // @SuppressWarnings(“unchecked”)を指定すると警告は出ず、実行時エラーの可能性ありstatic void copyAll(List<String> from, List<String>... tos) { List[] lists = tos; lists[0].add(new StringBuilder("A")); // 引数のデータを無理やり変更 lists[0].add(new StringBuilder("B")); // 引数のデータを無理やり変更 for(List<String> ls : tos) { for(String s : from) { ls.add(s); } }} SafeVarargsTest8.java:23: 警告: [unchecked] raw 型 List のメンバーとしての add(E) への無検査呼出しです lists[0].add(new StringBuilder("A")); // 引数のデータを無理やり変更 ^ E が型変数の場合: インタフェース List で宣言されている E extends Object SafeVarargsTest8.java:24: 警告: [unchecked] raw 型 List のメンバーとしての add(E) への無検査呼出しです lists[0].add(new StringBuilder("B")); // 引数のデータを無理やり変更 ^ E が型変数の場合: インタフェース List で宣言されている E extends Object © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 68
  69. 69. まとめ各々 できること・できないことがある Switch/case ラベルに文字列リテラル 整数リテラルの拡張記法 1つのcatchで複数例外をキャッチ ダイヤモンド(<>) リソース対応 try 文 @SafeVarargs アノテーション導入実行時エラーとなるケースは要注意 !! © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 69
  70. 70. © 2012 EIICHI KIMURA. All Rights Reserved. 2012/11/10 13:00-14:00 70

×