Java puzzlers 2013 at JavaFesta Japan
-
Upload
yoshio-terada -
Category
Technology
-
view
6.632 -
download
3
Transcript of Java puzzlers 2013 at JavaFesta Japan
JJaavvaa PPuuzzzzlleerrss AAttttaacckk ooff tthhee OObbjjeecctt##CClloonnee
櫻庭 祐一 寺田 佳央
コード中に発生する勘違い
� JJaavvaa プログラミングのパズル � 奇妙な振る舞いをする小さなプログラム � 複数の選択肢から、何が表示される? � ミステリーの解明 � 問題の解決方法 � 教訓
ルール:全て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)) その他 全員参加です
11 問目
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) ⼦子孫:祖先
正解は
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) 祖先:⼦子孫
� フィールドはコンパイル時に親クラスの情報を引き継ぎます � メソッドは実行時に上書きしたメソッドを呼び出します � 仮にどうしても子のフィールドにアクセスしたい場合、 キャストして取得します
11.解説
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) 祖先:⼦子孫
� フィールドは隠蔽し直接アクセスしないようにしてください
1.教訓
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(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
正解は
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
� RRaannddoommのコンストラクタは、乱数シードを指定します
� ループは11 ミリ秒の間に処理が完了します → 乱数シードが全て同一となります
� デフォルトコンスタクタはSSyysstteemm..nnaannooTTiimmee(())を使用 します
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");" }"}"
22.. 解決方法
� デフォルトのコンストラクタを使用してください
� テスト時など乱数系列をあえて同一にするテクニックもあります
22.教訓
33 問目
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)) ランタイム・エラー
正解は
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 を送出
� AArrrraayyss..aassLLiisstt は固定サイズのリストを生成します � aassLLiisstt(())で取得したリストに対して,, aadddd,, aaddddAAllll 等は 実行できません
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); } } }" 固定サイズのリストから、新たな可変リストを生成
33.. 解決方法
� 可変のリストを作成したい場合は、固定サイズのリストより新たな可変リストのコピーを生成します
33.. 教訓
4 問目
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)) それ以外
正解は
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))
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
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
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);" }"}"
� bbyyttee,, cchhaarr,, iinntt ,, lloonngg ((プリミティブ型)) を扱う場合、 桁のオーバフローを考慮した実装が必要です
� オーバフローを引き起こさないために BBiiggIInntteeggeerr を使う方法もあります
44.. 教訓
5 問目
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
正解は
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
� 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.. 解説
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.. 解決方法
� オートボクシングを使え便利になっていますが、 比較においては、pprriimmiittiivvee と OObbjjeecctt の比較は 十分に注意してください
� IInntteeggeerr の比較を行う際には iinnttVVaalluuee(()) での比較をお薦めします
55.. 教訓
6 問目
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
正解は
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
� ジェネリクスを指定しない場合、RRaaww 型といいます � RRaaww 型の場合、ジェネリクスの型情報が消失します つまり以下のクラスと同様になります
� そのため、SSttrriinngg のリストでも、iinntt wwrraapp((LLiisstt nnuummbbeerrss))が 実行され、実行時にCCllaassssCCaassttEExxcceeppttiioonnが発生します
public class WrapWrapWrap {" String wrap(Collection objs) {...} " int wrap(List numbers) {...} " ..."}"
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));" }"}"
66.. 解決方法 �
� ジェネリクスのパラメータは正しく指定しましょう
� JJaavvaa SSEE 77 からはダイヤモンド演算子が利用可能です
66.. 教訓
7 問目
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
正解は
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
� TTyyppee EErraassuurree :: � ジェネリクスはコンパイル時に解決され、コンパイル後型情報は消えます。そのためこれをイレイジャ方式と呼びます
� JJDDKK 55,, 66 では、同じイレイジャ・シグネチャを持つ、異なる返り値を持つメソッドの定義が可能でしたが、これは間違いで、JJDDKK 77 で修正されました。((RRFFEE :: 66118822995500))
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));" }"}"
JJaavvaa SSEE 77で実行 77.. 解決策
� 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個
JJaavvaa PPuuzzzzlleerrss AAttttaacckk ooff tthhee OObbjjeecctt##CClloonnee
櫻庭 祐一 寺田 佳央