Top Banner
ꜳꜳ Ꜳꜳ ꝏff ꝃÌꝏ 櫻庭 祐一 寺田 佳央
54

Java puzzlers 2013 at JavaFesta Japan

May 31, 2015

Download

Technology

Yoshio Terada
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java puzzlers 2013 at JavaFesta Japan

JJaavvaa PPuuzzzzlleerrss AAttttaacckk ooff tthhee OObbjjeecctt##CClloonnee

櫻庭 祐一 寺田 佳央

Page 2: Java puzzlers 2013 at JavaFesta Japan

コード中に発生する勘違い

�  JJaavvaa プログラミングのパズル � 奇妙な振る舞いをする小さなプログラム � 複数の選択肢から、何が表示される? � ミステリーの解明 � 問題の解決方法 � 教訓

Page 3: Java puzzlers 2013 at JavaFesta Japan

ルール:全て4択です

public class JavaPuzzlers {   public static void main(String... args) { "    http://www.java-users.jp   "    System.out.println(“Japan Java User Group Presents!”); } " } "

11))  JJaappaann JJaavvaa UUsseerrss GGrroouupp PPrreesseennttss!! 22))  JJaavvaa PPuuzzzzlleerrss 33))  00xxccaaffeebbaabbee 44))  その他 全員参加です

Page 4: Java puzzlers 2013 at JavaFesta Japan

11 問目

Page 5: Java puzzlers 2013 at JavaFesta Japan

1.. FFiinnddRRoooottss class Ancestor {" String name = "祖先”;" String getName() {return name;}"}"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());" }"}"

1)  祖先:祖先2)  ⼦子孫:⼦子孫3)  祖先:⼦子孫4)  ⼦子孫:祖先

Page 6: Java puzzlers 2013 at JavaFesta Japan

正解は

Page 7: Java puzzlers 2013 at JavaFesta Japan

class Ancestor {" String name = "祖先”;" String getName() {return name;}"}"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());" }"}"

1.. FFiinnddRRoooottss

3)  祖先:⼦子孫

Page 8: Java puzzlers 2013 at JavaFesta Japan

�  フィールドはコンパイル時に親クラスの情報を引き継ぎます �  メソッドは実行時に上書きしたメソッドを呼び出します �  仮にどうしても子のフィールドにアクセスしたい場合、   キャストして取得します

11.解説

Page 9: Java puzzlers 2013 at JavaFesta Japan

class Ancestor {" String name = "祖先”;" String getName() {return name;}"}"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());" }"}"

1.. 解決方法

3)  祖先:⼦子孫

Page 10: Java puzzlers 2013 at JavaFesta Japan

�  フィールドは隠蔽し直接アクセスしないようにしてください

1.教訓

Page 11: Java puzzlers 2013 at JavaFesta Japan

22 問目

Page 12: Java puzzlers 2013 at JavaFesta Japan

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");"  }"}"

22.MMaajjoorriittyyVVoottee 11))  YYEESS 22))  NNOO 33)) 場合による 44)) tthhrrooww EExxcceeppttiioonn

Page 13: Java puzzlers 2013 at JavaFesta Japan

正解は

Page 14: Java puzzlers 2013 at JavaFesta Japan

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");"  }"}"

22.MMaajjoorriittyyVVoottee 11))  YYEESS

Page 15: Java puzzlers 2013 at JavaFesta Japan

�  RRaannddoommのコンストラクタは、乱数シードを指定します

�  ループは11 ミリ秒の間に処理が完了します → 乱数シードが全て同一となります

�  デフォルトコンスタクタはSSyysstteemm..nnaannooTTiimmee(())を使用  します

22.解説

Page 16: Java puzzlers 2013 at JavaFesta Japan

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");"  }"}"

22.. 解決方法

Page 17: Java puzzlers 2013 at JavaFesta Japan

�  デフォルトのコンストラクタを使用してください

�  テスト時など乱数系列をあえて同一にするテクニックもあります

22.教訓

Page 18: Java puzzlers 2013 at JavaFesta Japan

33 問目

Page 19: Java puzzlers 2013 at JavaFesta Japan

public class CutAndPaste{ public static void main(String... argv) {"

   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);    }   } }"

33.CCuuttAAnnddPPaassttee 11)) 112233 22)) 112233445566 33)) コンパイル・エラー 44)) ランタイム・エラー

Page 20: Java puzzlers 2013 at JavaFesta Japan

正解は

Page 21: Java puzzlers 2013 at JavaFesta Japan

public class CutAndPaste { public static void main(String argv[]){"   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);    }   } }"

33.CCuuttAAnnddPPaassttee 44)) ランタイム・エラー

UUnnssuuppppoorrtteeddOOppeerraattiioonnEExxcceeppttiioonn を送出

Page 22: Java puzzlers 2013 at JavaFesta Japan

�  AArrrraayyss..aassLLiisstt は固定サイズのリストを生成します �  aassLLiisstt(())で取得したリストに対して,, aadddd,, aaddddAAllll 等は    実行できません

33.. 解説

Page 23: Java puzzlers 2013 at JavaFesta Japan

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);    }   } }" 固定サイズのリストから、新たな可変リストを生成

33.. 解決方法

Page 24: Java puzzlers 2013 at JavaFesta Japan

�  可変のリストを作成したい場合は、固定サイズのリストより新たな可変リストのコピーを生成します

33.. 教訓

Page 25: Java puzzlers 2013 at JavaFesta Japan

4 問目

Page 26: Java puzzlers 2013 at JavaFesta Japan

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.. WWaallttzzRRhhyytthhmm �

11)) 771155882277888822 ((== IInntteeggeerr..MMAAXX__VVAALLUUEE//33)) 22)) 771155882277888833 ((== IInntteeggeerr..MMAAXX__VVAALLUUEE//33 ++ 11)) 33)) 無限ループ 44)) それ以外

Page 27: Java puzzlers 2013 at JavaFesta Japan

正解は

Page 28: Java puzzlers 2013 at JavaFesta Japan

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.. WWaallttzzRRhhyytthhmm �

44)) それ以外 ((--771155882277888833))

Page 29: Java puzzlers 2013 at JavaFesta Japan

44.. 解説 �  IInntteeggeerr..MMAAXX__VVAALLUUEE == 22114477448833664477 �  ffoorr ((iinntt ii == 00;; ii << IInntteeggeerr..MMAAXX__VVAALLUUEE ;; ii ++== 33)) {{ �  ++33 インクリメントし ccoouunntt として771155882277888822を期待します

�  CCoouunntteerr がオーバフロー �  ffoorr 文の終了条件までIInntteeggeerr..MMIINN__VVAALLUUEE -->> IInntteeggeerr..MMAAXX__VVAALLUUEE を繰り返します

0 3 6 9 12 15 18 ・・・・・・・・・ 2147483646

1 2 3 4 5 6 7 715827883

i

counter

Page 30: Java puzzlers 2013 at JavaFesta Japan

44.. 解説 ffoorr ((iinntt ii == 00;; ii << IInntteeggeerr..MMAAXX__VVAALLUUEE ;; ii ++== 33))

0 3 6 9 12 15 18 ・・・・・・・・・ 2147483646

1 2 3 4 5 6 7 715827883 counter

・・・・・・・・・ 2147483645

-2147483648

-2147483647

715827884

-2147483647

715827885

2147483642

2147483647

・・・・・・・・・ 2147483644

-715827883

-2147483648

-2147483647

-2147483645

-2147483646

2147483641

-715827884

i

counter

i

counter

i

MAX_VALUE -1

MAX_VALUE -2 MIN_VALUE +2

MIN_VALUE +1

Page 31: Java puzzlers 2013 at JavaFesta Japan

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);" }"}"

Page 32: Java puzzlers 2013 at JavaFesta Japan

�  bbyyttee,, cchhaarr,, iinntt ,, lloonngg ((プリミティブ型)) を扱う場合、  桁のオーバフローを考慮した実装が必要です

�  オーバフローを引き起こさないために BBiiggIInntteeggeerr を使う方法もあります

44.. 教訓

Page 33: Java puzzlers 2013 at JavaFesta Japan

5 問目

Page 34: Java puzzlers 2013 at JavaFesta Japan

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));"}"

55.. UUppppeerrLLoowweerrMMaattcchh

11)) ttrruuee ttrruuee ttrruuee ttrruuee 22)) ffaallssee ttrruuee ffaallssee ttrruuee 33)) ttrruuee ffaallssee ttrruuee ffaallssee 44)) ttrruuee ttrruuee ttrruuee ffaallssee

Page 35: Java puzzlers 2013 at JavaFesta Japan

正解は

Page 36: Java puzzlers 2013 at JavaFesta Japan

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));"}"

55.. UUppppeerrLLoowweerrMMaattcchh

44)) ttrruuee ttrruuee ttrruuee ffaallssee

Page 37: Java puzzlers 2013 at JavaFesta Japan

�  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 で変更可能"

55.. 解説

Page 38: Java puzzlers 2013 at JavaFesta Japan

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()));"}"

55.. 解決方法

Page 39: Java puzzlers 2013 at JavaFesta Japan

�  オートボクシングを使え便利になっていますが、      比較においては、pprriimmiittiivvee と OObbjjeecctt の比較は     十分に注意してください

�  IInntteeggeerr の比較を行う際には iinnttVVaalluuee(()) での比較をお薦めします

55.. 教訓

Page 40: Java puzzlers 2013 at JavaFesta Japan

6 問目

Page 41: Java puzzlers 2013 at JavaFesta Japan

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));" }"}"

66.. WWrraappWWrraappWWrraapp� 11))  66 22))  112233 33))  CCoommppiillee EErrrroorr 44))  tthhrrooww EExxcceeppttiioonn

Page 42: Java puzzlers 2013 at JavaFesta Japan

正解は

Page 43: Java puzzlers 2013 at JavaFesta Japan

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));" }"}"

66.. WWrraappWWrraappWWrraapp�44)) tthhrrooww EExxcceeppttiioonn

Page 44: Java puzzlers 2013 at JavaFesta Japan

�  ジェネリクスを指定しない場合、RRaaww 型といいます �  RRaaww 型の場合、ジェネリクスの型情報が消失します つまり以下のクラスと同様になります

�  そのため、SSttrriinngg のリストでも、iinntt wwrraapp((LLiisstt nnuummbbeerrss))が   実行され、実行時にCCllaassssCCaassttEExxcceeppttiioonnが発生します

public class WrapWrapWrap {" String wrap(Collection objs) {...} " int wrap(List numbers) {...} " ..."}"

66.. 解説

Page 45: Java puzzlers 2013 at JavaFesta Japan

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));" }"}"

66.. 解決方法 �

Page 46: Java puzzlers 2013 at JavaFesta Japan

�  ジェネリクスのパラメータは正しく指定しましょう

�  JJaavvaa SSEE 77 からはダイヤモンド演算子が利用可能です

66.. 教訓

Page 47: Java puzzlers 2013 at JavaFesta Japan

7 問目

Page 48: Java puzzlers 2013 at JavaFesta Japan

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  ,  1003)  コンパイルエラー4)  ランタイムエラー

JJaavvaa SSEE 6で実行 77.. LLoossttAAnnddFFoouunndd

Page 49: Java puzzlers 2013 at JavaFesta Japan

正解は

Page 50: Java puzzlers 2013 at JavaFesta Japan

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)  ランタイムエラー

JJaavvaa SSEE 6で実行 77.. LLoossttAAnnddFFoouunndd

Page 51: Java puzzlers 2013 at JavaFesta Japan

�  TTyyppee EErraassuurree :: �  ジェネリクスはコンパイル時に解決され、コンパイル後型情報は消えます。そのためこれをイレイジャ方式と呼びます

�  JJDDKK 55,, 66 では、同じイレイジャ・シグネチャを持つ、異なる返り値を持つメソッドの定義が可能でしたが、これは間違いで、JJDDKK 77 で修正されました。((RRFFEE :: 66118822995500))

77.. 解説

Page 52: Java puzzlers 2013 at JavaFesta Japan

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));" }"}"

JJaavvaa SSEE 77で実行 77.. 解決策

Page 53: Java puzzlers 2013 at JavaFesta Japan

�  JJaavvaa SSEE 77 へ移行してください ((コンパイルエラー))

�  JJaavvaa のバージョン・アップ時には JJaavvaa の互換性・非互換性情報も必ずご確認ください

77.. 教訓

http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#incompatibilities

LostAndFound.java:8: エラー: 名前が競合しています。getArticles(List<Integer>)とgetArticles(List<String>)は削除後の名前が同じです static long getArticles(List<Integer> list) { return 200; }" ^"エラー1個

Page 54: Java puzzlers 2013 at JavaFesta Japan

JJaavvaa PPuuzzzzlleerrss AAttttaacckk ooff tthhee OObbjjeecctt##CClloonnee

櫻庭 祐一 寺田 佳央