Java puzzlers 2013 at JavaFesta Japan

7,406 views

Published on

0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,406
On SlideShare
0
From Embeds
0
Number of Embeds
5,006
Actions
Shares
0
Downloads
11
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

Java puzzlers 2013 at JavaFesta Japan

  1. 1. JJaavvaa PPuuzzzzlleerrss AAttttaacckk ooff tthhee OObbjjeecctt##CClloonnee 櫻庭 祐一 寺田 佳央
  2. 2. コード中に発生する勘違い —  JJaavvaa プログラミングのパズル —  奇妙な振る舞いをする小さなプログラム —  複数の選択肢から、何が表示される? —  ミステリーの解明 —  問題の解決方法 —  教訓
  3. 3. ルール:全て4択です public class JavaPuzzlers {
   public static void main(String... args) { "     http://www.java-users.jp   "     System.out.println(“Japan Java User Group Presents!”); } " } " 11))  22))  33))  44))  JJaappaann JJaavvaa UUsseerrss GGrroouupp PPrreesseennttss!! JJaavvaa PPuuzzzzlleerrss 00xxccaaffeebbaabbee その他 全員参加です
  4. 4. 11 問目
  5. 5. 1.. FFiinnddRRoooottss class Ancestor {" String name = "祖先”;" 1)  祖先:祖先 String getName() {return name;}" 2)  ⼦子孫:⼦子孫 }" 3)  祖先:⼦子孫 class Descendant extends Ancestor {" 4)  ⼦子孫:祖先 String name = "子孫";" @Override" String getName() {return name;}" }" " public class FindRoots {" public static void main(String argv[]) {" Ancestor person = new Descendant();" System.out.println(" person.name + ":" + person.getName());" }" }"
  6. 6. 正解は
  7. 7. 1.. FFiinnddRRoooottss class Ancestor {" String name = "祖先”;" String getName() {return name;}" }" 3)  祖先:⼦子孫 class Descendant extends Ancestor {" String name = "子孫";" @Override" String getName() {return name;}" }" " public class FindRoots {" public static void main(String argv[]) {" Ancestor person = new Descendant();" System.out.println(" person.name + ":" + person.getName());" }" }"
  8. 8. 11.解説 —  フィールドはコンパイル時に親クラスの情報を引き継ぎます —  メソッドは実行時に上書きしたメソッドを呼び出します —  仮にどうしても子のフィールドにアクセスしたい場合、    キャストして取得します
  9. 9. 1.. 解決方法 class Ancestor {" String name = "祖先”;" String getName() {return name;}" }" 3)  祖先:⼦子孫 class Descendant extends Ancestor {" String name = "子孫";" @Override" String getName() {return name;}" }" " public class FindRoots {" public static void main(String argv[]) {" Ancestor person = new Descendant();" System.out.println(" ((Descendant)person).name + ":" + person.getName());" }" }"
  10. 10. 1.教訓 —  フィールドは隠蔽し直接アクセスしないようにしてください
  11. 11. 22 問目
  12. 12. 22.MMaajjoorriittyyVVoottee 11))  YYEESS 22))  NNOO 33)) 場合による 44)) tthhrrooww EExxcceeppttiioonn public class MajorityVote {" public static void main(String... args) {"    Random[] randoms = new Random[10];"     for (int i = 0; i < 10; i++)"      randoms[i] = new Random(System.currentTimeMillis());" " int count = 0;"     boolean option = randoms[0].nextBoolean();"     for (int i = 1; i < 10; i++)"       if (option == randoms[i].nextBoolean()) count++;" "     System.out.println((count > 5)? "YES": "NO");"   }" }"
  13. 13. 正解は
  14. 14. 22.MMaajjoorriittyyVVoottee 11))  YYEESS public class MajorityVote {" public static void main(String... args) {"    Random[] randoms = new Random[10];"     for (int i = 0; i < 10; i++)"      randoms[i] = new Random(System.currentTimeMillis());" " int count = 0;"     boolean option = randoms[0].nextBoolean();"     for (int i = 1; i < 10; i++)"       if (option == randoms[i].nextBoolean()) count++;" "     System.out.println((count > 5)? "YES": "NO");"   }" }"
  15. 15. 22.解説 —  RRaannddoommのコンストラクタは、乱数シードを指定します —  ループは11 ミリ秒の間に処理が完了します → 乱数シードが全て同一となります —  デフォルトコンスタクタはSSyysstteemm..nnaannooTTiimmee(())を使用   します
  16. 16. 22.. 解決方法 public class MajorityVote {" public static void main(String... args) {"    Random[] randoms = new Random[10];"     for (int i = 0; i < 10; i++)"      randoms[i] = new Random();" " int count = 0;"     boolean option = randoms[0].nextBoolean();"     for (int i = 1; i < 10; i++)"       if (option == randoms[i].nextBoolean()) count++;" "     System.out.println((count > 5)? "YES": "NO");"   }" }"
  17. 17. 22.教訓 —  デフォルトのコンストラクタを使用してください —  テスト時など乱数系列をあえて同一にするテクニックもあり ます
  18. 18. 33 問目
  19. 19. 33.CCuuttAAnnddPPaassttee 11)) 112233 22)) 112233445566 public class CutAndPaste{
 33)) コンパイル・エラー public static void main(String... argv) {" 44)) ランタイム・エラー    String firstLine = "1,2,3";
   String secondLine = "4,5,6";
    List<String> firstList = "   Arrays.asList(firstLine.split(”,"));
 List<String> secondList = " Arrays.asList(secondLine.split(”,"));
    firstList.addAll(secondList);
    for(String data : firstList){
   System.out.print(data);
    }
   }
 }"
  20. 20. 正解は
  21. 21. 33.CCuuttAAnnddPPaassttee public class CutAndPaste {
 public static void main(String argv[]){" 44)) ランタイム・エラー    String firstLine = "1,2,3";
   String secondLine = "4,5,6";
    List<String> firstList = " "Arrays.asList(firstLine.split(","));
   List<String> secondList =" "Arrays.asList(secondLine.split(","));
    firstList.addAll(secondList);
    for(String data : firstList){
   System.out.print(data);
    }
   }
 }" UUnnssuuppppoorrtteeddOOppeerraattiioonnEExxcceeppttiioonn を送出
  22. 22. 33.. 解説 —  AArrrraayyss..aassLLiisstt は固定サイズのリストを生成します —  aassLLiisstt(())で取得したリストに対して,, aadddd,, aaddddAAllll 等は     実行できません
  23. 23. 33.. 解決方法 public class CutAndPaste {
 public static void main(String argv[]) {"    String firstLine = "1,2,3";
   String secondLine = "4,5,6";
    List<String> firstList = new ArrayList<>("   Arrays.asList(firstLine.split(",")));
 List<String> secondList = " Arrays.asList(secondLine.split(","));
    firstList.addAll(secondList);
    for(String data : firstList){
   System.out.print(data);
    }
   }
 }" 固定サイズのリストから、新たな可変リストを生成
  24. 24. 33.. 教訓 —  可変のリストを作成したい場合は、固定サイズのリストより 新たな可変リストのコピーを生成します
  25. 25. 4 問目
  26. 26. 44.. WWaallttzzRRhhyytthhmm public class WaltzRhythm {" public static void main(String... args) {" int count = 0;" for (int i = 0; i < Integer.MAX_VALUE; i += 3) {" count++;" }" System.out.println(count);" }" }" 11)) 771155882277888822 ((== IInntteeggeerr..MMAAXX__VVAALLUUEE//33)) 22)) 771155882277888833 ((== IInntteeggeerr..MMAAXX__VVAALLUUEE//33 ++ 11)) 33)) 無限ループ 44)) それ以外
  27. 27. 正解は
  28. 28. 44.. WWaallttzzRRhhyytthhmm public class WaltzRhythm {" public static void main(String... args) {" int count = 0;" for (int i = 0; i < Integer.MAX_VALUE; i += 3) {" count++;" }" System.out.println(count);" }" }" 44)) それ以外 ((--771155882277888833))
  29. 29. 44.. 解説 —  IInntteeggeerr..MMAAXX__VVAALLUUEE == 22114477448833664477 —  ffoorr ((iinntt ii == 00;; ii << IInntteeggeerr..MMAAXX__VVAALLUUEE ;; ii ++== 33)) {{ —  ++33 インクリメントし ccoouunntt として771155882277888822を期待します counter 1 2 3 4 5 6 7 0 3 6 9 12 15 18 i 715827883 ・・・・・・・・・ 2147483646 —  CCoouunntteerr がオーバフロー —  ffoorr 文の終了条件までIInntteeggeerr..MMIINN__VVAALLUUEE -->> IInntteeggeerr..MMAAXX__VVAALLUUEE を繰り返し ます
  30. 30. 44.. 解説 ffoorr ((iinntt ii == 00;; ii << IInntteeggeerr..MMAAXX__VVAALLUUEE ;; ii ++== 33)) counter 1 2 3 4 5 6 7 715827883 i 0 3 6 9 12 15 18 ・・・・・・・・・ 2147483646 MAX_VALUE -1 counter 715827884 i 715827885 2147483642 2147483645 -2147483647 -2147483647 ・・・・・・・・・ MIN_VALUE +2 counter -2147483647 -2147483646 i 2147483647 -2147483648 MAX_VALUE -2 -715827884 -715827883 2147483641 2147483644 -2147483648 -2147483645 ・・・・・・・・・ MIN_VALUE +1
  31. 31. 44.. 解決方法 public class WaltzRhythm {" public static void main(String... args) {" int count = 0;" for (int i = 0; i < Integer.MAX_VALUE -3 ; i += 3) {" count++;" }" System.out.println(count);" }" }"
  32. 32. 44.. 教訓 —  bbyyttee,, cchhaarr,, iinntt ,, lloonngg ((プリミティブ型)) を扱う場合、   桁のオーバフローを考慮した実装が必要です —  オーバフローを引き起こさないために BBiiggIInntteeggeerr を使う方 法もあります
  33. 33. 5 問目
  34. 34. 55.. UUppppeerrLLoowweerrMMaattcchh public class UpperLowerMatch {" public static void main(String argv[]){" Integer a1 = 10; Integer a2 = 129;" int b1 = 10; int b2 = 129;" Integer c1 = 10; Integer c2 = 129;" " System.out.print((a1==b1));" System.out.print("t”+(a1==c1));" " System.out.print("t”+(a2==b2));" System.out.println("t”+(a2==c2));" 11)) ttrruuee ttrruuee ttrruuee ttrruuee }" 22)) ffaallssee ttrruuee ffaallssee ttrruuee 33)) ttrruuee ffaallssee ttrruuee ffaallssee 44)) ttrruuee ttrruuee ttrruuee ffaallssee
  35. 35. 正解は
  36. 36. 55.. UUppppeerrLLoowweerrMMaattcchh public class UpperLowerMatch {" public static void main(String argv[]){" Integer a1 = 10; Integer a2 = 129;" int b1 = 10; int b2 = 129;" Integer c1 = 10; Integer c2 = 129;" " System.out.print((a1==b1));" System.out.print("t”+(a1==c1));" " System.out.print("t”+(a2==b2));" System.out.println("t”+(a2==c2));" }" 44)) ttrruuee ttrruuee ttrruuee ffaallssee
  37. 37. 55.. 解説 —  AAuuttooBBooxxiinngg —  プリミティブとオブジェクトの比較は、プリミティブで計算し比較 —  オブジェクトとオブジェクトの比較は、オブジェクトの参照で比較 —  JJaavvaa..llaanngg..IInntteeggeerr は--112288 から 112277 の値の範囲でオブ ジェクト IIDDの値をキャッシュしており、その比較を実施し ます —  つまり値が --112288 から 112277 の範囲か否かで結果が異なります Cache to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive) as required by JLS. " キャッシュ範囲は -XX:AutoBoxCacheMax で変更可能"
  38. 38. 55.. 解決方法 public class UpperLowerMatch {" public static void main(String argv[]){" Integer a1 = 10; Integer a2 = 129;" int b1 = 10; int b2 = 129;" Integer c1 = 10; Integer c2 = 129;" " System.out.print((a1==b1));" System.out.print("t” + (a1.intValue()==c1.intValue()));" " System.out.print("t” + (a2==b2));" System.out.println((a2.intValue()==c2.intValue()));" }"
  39. 39. 55.. 教訓 —  オートボクシングを使え便利になっていますが、       比較においては、pprriimmiittiivvee と OObbjjeecctt の比較は      十分に注意してください —  IInntteeggeerr の比較を行う際には iinnttVVaalluuee(()) での比較をお薦め します
  40. 40. 6 問目
  41. 41. 66.. WWrraappWWrraappWWrraapp 11))  22))  33))  44))  66 112233 CCoommppiillee EErrrroorr tthhrrooww EExxcceeppttiioonn public class WrapWrapWrap<T> {" String wrap(Collection<?> objs) {" String result = "";" for (Object o: objs) result += o;" return result;" } " int wrap(List<Integer> numbers) {" int result = 0;" for (int num: numbers) result += num;" return result;" } " public static void main(String... args) {" List<String> strings = Arrays.asList("1", "2", "3");" System.out.println(new WrapWrapWrap().wrap(strings));" }" }"
  42. 42. 正解は
  43. 43. 66.. WWrraappWWrraappWWrraapp public class WrapWrapWrap<T> {" String wrap(Collection<?> objs) {" 44)) tthhrrooww EExxcceeppttiioonn String result = "";" for (Object o: objs) result += o;" return result;" } " int wrap(List<Integer> numbers) {" int result = 0;" for (int num: numbers) result += num;" return result;" } " public static void main(String... args) {" List<String> strings = Arrays.asList("1", "2", "3");" System.out.println(new WrapWrapWrap().wrap(strings));" }" }"
  44. 44. 66.. 解説 —  ジェネリクスを指定しない場合、RRaaww 型といいます —  RRaaww 型の場合、ジェネリクスの型情報が消失します つまり以下のクラスと同様になります public class WrapWrapWrap {" String wrap(Collection objs) {...} int wrap(List numbers) {...} " ..." }" " —  そのため、SSttrriinngg のリストでも、iinntt wwrraapp((LLiisstt nnuummbbeerrss))が    実行され、実行時にCCllaassssCCaassttEExxcceeppttiioonnが発生します
  45. 45. 66.. 解決方法 public class WrapWrapWrap<T> {" String wrap(Collection<?> objs) {" String result = "";" for (Object o: objs) result += o;" return result;" }" int wrap(List<Integer> numbers) {" int result = 0;" for (int num: numbers) result += num;" return result;" }" public static void main(String... args) {" List<String> strings = Arrays.asList("1", "2", "3");" System.out.println(new WrapWrapWrap<String>().wrap(strings));" }" }"
  46. 46. 66.. 教訓 —  ジェネリクスのパラメータは正しく指定しましょう —  JJaavvaa SSEE 77 からはダイヤモンド演算子が利用可能です
  47. 47. 7 問目
  48. 48. 77.. LLoossttAAnnddFFoouunndd JJaavvaa SSEE 6で実行 public class LostAndFound {" static int getArticles(List<String> list) { return 100; }" static long getArticles(List<Integer> list) { return 200; }" public static void main(String argv[]){" List<String> listStr = new ArrayList<String>();" List<Integer> listInt = new ArrayList<Integer>();" System.out.println(getArticles(listStr));" System.out.println(getArticles(listInt));" }" }" 1)  100  ,  200 2)  200  ,  100 3)  コンパイルエラー 4)  ランタイムエラー
  49. 49. 正解は
  50. 50. 77.. LLoossttAAnnddFFoouunndd JJaavvaa SSEE 6で実行 public class LostAndFound {" static int getArticles(List<String> list){ return 100;}" static long getArticles(List<Integer> list) { return 200; }" public static void main(String argv[]){" List<String> listStr = new ArrayList<String>();" List<Integer> listInt = new ArrayList<Integer>();" System.out.println(getArticles(listStr));" System.out.println(getArticles(listInt));" }" }" 4)  ランタイムエラー
  51. 51. 77.. 解説 —  TTyyppee EErraassuurree :: —  ジェネリクスはコンパイル時に解決され、コンパイル後型情報 は消えます。そのためこれをイレイジャ方式と呼びます —  JJDDKK 55,, 66 では、同じイレイジャ・シグネチャを持つ、異な る返り値を持つメソッドの定義が可能でしたが、これは間違 いで、JJDDKK 77 で修正されました。((RRFFEE :: 66118822995500))
  52. 52. 77.. 解決策 JJaavvaa SSEE 77で実行 public class LostAndFound {" static int getArticles(List<String> list) { return 100; }" static long getArticles(List<Integer> list) { return 200; }" public static void main(String argv[]){" List<String> listStr = new ArrayList<>();" List<Integer> listInt = new ArrayList<>();" System.out.println(getArticles(listStr));" System.out.println(getArticles(listInt));" }" }"
  53. 53. 77.. 教訓 —  JJaavvaa SSEE 77 へ移行してください ((コンパイルエラー)) LostAndFound.java:8: エラー: 名前が競合しています。 getArticles(List<Integer>)とgetArticles(List<String>)は削除後の名前が 同じです static long getArticles(List<Integer> list) { return 200; }" ^" エラー1個 —  JJaavvaa のバージョン・アップ時には JJaavvaa の互換性・非互換 性情報も必ずご確認ください http://www.oracle.com/technetwork/java/javase/ compatibility-417013.html#incompatibilities
  54. 54. JJaavvaa PPuuzzzzlleerrss AAttttaacckk ooff tthhee OObbjjeecctt##CClloonnee 櫻庭 祐一 寺田 佳央

×