javaで最強のfizz buzz
Post on 20-Mar-2017
2.460 Views
Preview:
TRANSCRIPT
Javaで最強のFizzBuzz
第16回 渋谷じゃば 2016/07/23
@yy_yank
こいつです
・小物SIer ・viキーバインド好き
・サクラエディタicon ・JavaとKotlinが好き
ヤンク(@yy_yank)
自己紹介
FizzBuzzとは
3の倍数ではFizzを出力して、5の倍数ではBuzzを出力して、 両方の倍数(15の倍数)の場合はFizzBuzzと出力して、それ以外は数字をそのまま出力する処理のことを言います
FizzBuzzとは
なるほど
public void fizzBuzz() throws Exception { IntStream.rangeClosed(0, 10000).mapToObj(FizzBuzz::make).forEach(System.out::println);}private static String make(int i) { return i != 0 && i % 15 == 0 ? "fizzbuzz" : i != 0 && i % 3 == 0 ? "fizz" : i != 0 && i % 5 == 0 ? "buzz" : String.valueOf(i);}
適当にやるならこんな感じ
特に説明は不要ですよね
設計を考える
・言語規約を守る
・適切なインターフェースを実装する
Javaの設計で大事なこと
3の倍数ではFizzを出力して、5の倍数ではBuzzを出力して、 両方の倍数(15の倍数)の場合はFizzBuzzと出力して、それ以外は数字をそのまま出力する処理のことを言います
要件を改めて見る
3の倍数ではFizzを出力して、
5の倍数ではBuzzを出力して、 両方の倍数(15の倍数)の場合はFizzBuzzと出力して、それ以外は数字をそのまま出力する処理のことを言います
要件を改めて見る
FizzBuzzFizzBuzzSonomama
クラス構成
Fizz・・・fizzと出力
Buzz・・・buzzと出力
FizzBuzz・・・fizzbuzzと出力
Sonomama・・・そのまま数字を出力
なにをするか
Fizz・・・3で割り切れたら
Buzz・・・5で割り切れたら
FizzBuzz・・・15で割り切れたら
Sonomama・・・3でも5でも15でも割り切れない
どのタイミングか
よし、いけそう
じゃあ、どうやって処理伝播をしよう
投げよう
これが最強のクラス構成だ
FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException
FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException
これが最強のクラス構成だ
投げる
FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException
これが最強のクラス構成だ
投げられる
FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException
これが最強のクラス構成だ
持ちつ
FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException
これが最強のクラス構成だ
持たれつ
public class FizzBuzzPitcher { private FizzBuzzPitcher(){} public static void overThrow(int i) { boolean fizz = i != 0 && i % 3 == 0; boolean buzz = i != 0 && i % 5 == 0; boolean fizzBuzz = i != 0 && i % 15 == 0; if(fizzBuzz) { throw new FizzBuzzException(); } else if(fizz) { throw new FizzException(); } else if(buzz) { throw new BuzzException(); } else { throw new SonomamaException(i); }}
これが最強のピッチャーだ
for (int i = 0; i < 10000; i++) try { FizzBuzzPitcher.overThrow(i); } catch (FizzException fizz) { System.out.println("fizz"); } catch (BuzzException buzz) { System.out.println("buzz"); } catch (FizzBuzzException fizzbuzz) { System.out.println("fizzbuzz"); } catch (SonomamaException not) { System.out.println(i); }
これが最強の処理実行だ
完璧ですね
いやチョット待て
おかしいおかしい
for (int i = 0; i < 10000; i++) try { FizzBuzzPitcher.overThrow(i); } catch (FizzException fizz) { System.out.println("fizz"); } catch (BuzzException buzz) { System.out.println("buzz"); } catch (FizzBuzzException fizzbuzz) { System.out.println("fizzbuzz"); } catch (SonomamaException not) { System.out.println(i); }
これが最強の処理実行だ
このあたりが冗長!!!
#そこかよ
じゃあ、どうやって冗長さをなくそう
AutoClosableを使おう
FizzException implements AutoClosableBuzzException implements AutoClosableFizzBuzzException implements AutoClosableSonomamaException implements AutoClosableFizzBuzzCatcher
これが最強のクラス構成だ
public class BuzzException extends RuntimeException implements AutoCloseable{ @Override public void close() { System.out.println(“buzz”); }}
これが最強のclose処理だ
これが最強のキャッチャーだpublic class FizzBuzzCatcher { private FizzBuzzCatcher(){} public static AutoCloseable make(int i) { try { FizzBuzzPitcher.overThrow(i); } catch(FizzException | BuzzException | FizzBuzzException | SonomamaException e){ return (AutoCloseable) e; } // 投げられないのはおかしいから投げる
throw new IllegalStateException(); } public static void receive(int i) throws Exception { try(AutoCloseable ex = make(i)){} }}
public class FizzBuzzCatcher { private FizzBuzzCatcher(){} public static AutoCloseable make(int i) { try { FizzBuzzPitcher.overThrow(i); } catch(FizzException | BuzzException | FizzBuzzException | SonomamaException e){ return (AutoCloseable) e; } // 投げられないのはおかしいから投げる
throw new IllegalStateException(); } public static void receive(int i) throws Exception { try(AutoCloseable ex = make(i)){} }}
これが最強のキャッチャーだ
try-with-resourecesで処理が呼び出される
これでインスタンス生成するだけで標準出力されるぞ!!
これが最強の処理実行だ
// なんと呼び出し側は1行!!!
for (int i = 0; i < 10000; i++) FizzBuzzCatcher.receive(i);
・時として、人類は間違いをおかす
・誰かが止めなければならない
・例外は異常を伝えるために使いましょう
・例外をgoto文のように使ってはいけません
・AutoClosableインターフェースはクローズ処理を行うために使いましょう
※ちなみにjava.util.stream.Streamも
AutoCloseableです
まとめ
・言語規約を守る
・適切なインターフェースを実装する
Javaの設計で大事なこと
動けば良い、は良くない!!
時間が余ったらおまけ
これが最強のキャッチャーだpublic class FizzBuzzCatcher { private FizzBuzzCatcher(){} public static AutoCloseable make(int i) { try { FizzBuzzPitcher.overThrow(i); } catch(FizzException | BuzzException | FizzBuzzException | SonomamaException e){ return (AutoCloseable) e; } // 投げられないのはおかしいから投げる
throw new IllegalStateException(); } public static void receive(int i) throws Exception { try(AutoCloseable ex = make(i)){} }}
こういうふざけたコードを書いてたら Javaコンパイラのバグを踏みました※1.8.0_25のバグで、1.8.0_72で直ってます
14:39:40: Executing external task 'build'...コンパイラで例外が発生しました(1.8.0_25)。Bug Paradeで重複がないかをご確認のうえ、Java Developer Connection (http://java.sun.com/webapps/bugreport)でbugの登録をお願いいたします。レポートには、そのプログラムと
下記の診断内容を含めてください。ご協力ありがとうございます。java.lang.ClassCastException: com.sun.tools.javac.code.Type$UnionClassType cannot be cast to com.sun.tools.javac.code.Type$IntersectionClassType
at com.sun.tools.javac.code.Types$8.visitClassType(Types.java:1540)at com.sun.tools.javac.code.Types$8.visitClassType(Types.java:1497)at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)at com.sun.tools.javac.code.Types$DefaultTypeVisitor.visit(Types.java:4451)at com.sun.tools.javac.code.Types.isCastable(Types.java:1488)at com.sun.tools.javac.comp.Check.checkCastable(Check.java:568)at com.sun.tools.javac.comp.Check.checkCastable(Check.java:565)
[JDK-8071291]Compiler crashes trying to cast UnionType to IntersectionClassTypehttps://bugs.openjdk.java.net/browse/JDK-8071291
バグレポートの書き方http://yyyank.blogspot.jp/2016/07/javajdk.html
top related