Edited at

現役エンジニアに不評な新人向けJavaプログラミング演習課題

現役エンジニアに見せると大体渋い顔をして「新人には難しいと思う」と言われます。

言葉や表現が難しいかもしれないということらしいです。


前提

これは Java の基礎を理解した(と思っている)程度の新人を対象とする教育用の演習課題として作成したものです。教育用なので、最初からすべて解答できる想定ではありません。制限時間は適宜。

(すべて難なく解答できる人は1機能を任せながら適宜教えるくらいです)

知らない言葉を調べて理解できるかどうかも知りたいので、多分知らないであろう言葉を敢えて使っています。

解答する際のアプローチ、詰まるポイント、間違え方等を見ながら、それに応じて随時指導するとともに、今後の教育方針等を決める参考情報を得るためのものです。


課題.1

次のように動作するインスタンスメソッド「practice(final String n)」を持つクラス「exam.Exam1」を作成してください。


  • 文字列 n が、1以上の数字でない場合、「エラー」という文字列を "標準エラー出力" に出力して処理を中断する。

  • 1 から n まで数え上げ、数字を改行区切りで "標準出力" に出力。

  • 3の倍数の時は数字の代わりに「Fizz」を1行で出力。

  • 5の倍数の時は数字の代わりに「Buzz」を1行で出力。

  • 3の倍数かつ5の倍数の場合は「FizzBuzz」が1行で出力されること。

  • 3 の付く数字の一覧をカンマ(,)区切りで列挙し、「 are contains "3".」を付記して contains3.txt ファイルに出力する。


課題.2

「課題.1」で作成したクラス「Exam1」を下記の条件に合うように変更したクラス「exam.Exam2」を作成してください。


  • 文字列 n が、1以上の数字でない場合、例外「IllegalArgumentException」を発生させる。

  • 素数の時は数字の代わりに「Fizz」を1行で出力。

  • 3の倍数の時は数字の代わりに「Buzz」を1行で出力。

  • 3の倍数かつ素数の場合は「FizzBuzz」が出力されること。

  • 素数の一覧をカンマ(,)区切りで列挙し、「are the numbers of primes.」を付記して .txt ファイルに出力する。


課題.3

次のコードで示すようなインターフェース「exam.FizzBuzz」を実装し、下記の条件を満たすように「exam3.Exam1」「exam3.Exam2」を作成してください。


  • 戻り値 List は、「課題.1, 課題.2」で作成した「exam.Exam1」「exam.Exam2」の「practice」メソッドで標準出力している1行(改行を除く)を要素とする。

  • 引数 n に対して、「practice」メソッドで標準出力する行がない場合は空のリストを返す。


exam.FizzBuzz.java

    package exam;

// import … (省略);
public interface FizzBuzz {
public List<String> fizzBuzz(final int n);
}


課題.4

下記の条件を満たすような、抽象クラス「exam.AbstractFizzBuzz」と、それを継承する「exam4.Exam1」「exam4.Exam2」を作成してください。


  • 抽象クラス「exam.AbstractFizzBuzz」は、「課題.3」の「exam.FizzBuzz」インターフェースを実装すること。

  • インターフェース「exam.FizzBuzz」の「fizzBuzz」メソッドは「exam.AbstractFizzBuzz」で実装するものとし、 「exam4.Exam1」「exam4.Exam2」ではOverride禁止

※ ヒント: テンプレートメソッド


課題.5-1

次のコードで示すような抽象クラス「exam.AbstractFizzBuzz」を継承する「exam5.Exam1」「exam5.Exam2」を作成してください。

ただし、 isFizz, isBuzz の条件は「課題.1, 課題.2」で実装した条件と同じとします。


exam.FizzBuzzStrategy.java

    package exam;

// import … (省略);
public interface FizzBuzzStrategy {
boolean isFizz(final int num); // Fizz となる場合 true
boolean isBuzz(final int num); // Buzz となる場合 true
String fizz(); // Fizz を返す
String buzz(); // Buzz を返す
String both(); // FizzBuzz を返す
}


exam.AbstractFizzBuzz.java

    package exam;

// import … (省略);
public abstract class AbstractFizzBuzz implements FizzBuzzStrategy {
@Override
String fizz() { return "Fizz"; }
@Override
String buzz() { return "Buzz"; }
@Override
String both() { return "FizzBuzz"; }
}

※ ヒント: ストラテジーパターン


課題.5-2

次のコードで示すような「exam.FizzBuzzRunner」を考えます。

実行結果が以下の「実行例」通りになるように run メソッドを実装してください。

必要であれば「課題.5-1」で作成したクラスについても変更しても構いません。


exam.FizzBuzzRunner.java

    package exam;

// import … (省略);
public class FizzBuzzRunner {

public static void main(String[] args) {

final FizzBuzzRunner runner = new FizzBuzzRunner();

final List<String> exam1FizzBuzz = runner.run(21, new exam5.Exam1());
print(exam1FizzBuzz);

System.out.println("----------");

final List<String> exam2FizzBuzz = runner.run(16, new exam5.Exam2());
print(exam2FizzBuzz);
}

private static void print(final List<String> src) {
for (String s : src) {
System.out.println(s);
}
}

public List<String> run(final int n, final FizzBuzzStrategy strategy) {
// ※ ここを実装
}
}



実行例:

        1

2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
----------
1
Fizz
FizzBuzz
4
Fizz
Buzz
Fizz
8
Buzz
10
Fizz
Buzz
Fizz
14
Buzz
16
17
Buzz
Fizz
20
Buzz