ここでは、カプセル化に関するJavaプログラムを作成してみましょう。

1.データ隠蔽

以下のクラスにデータ隠蔽を施しなさい。

1度目はIDEの便利機能を使用せず、2度めは使用して作成してみること。

package p11;

public class Q01 {
    int id;
    String name;
    boolean programmingExperience;
}

2.アクセサメソッドの効果

1で作成したクラスのアクセサメソッドに追記することにより以下の制約を課しなさい。

  • IDは整数4桁の数値 1000~9999
  • 名前は最低5文字以上
  • なお、制約を外れた値の設定に対しては何もしない
  • コンストラクタはなし(デフォルトコンストラクタ)

作成後に別途、テストクラスを用意して動作を確かめること。

<出力例:入力制約を満たす場合>

1000
imaikatsuya

<出力例:IDに10、名前にimaiを設定した場合>

0
null

3.PINコードのクラッキング

銀行のATM等で利用されるPINコードのプロトタイプとして次のようなクラスがある。

package p11;

class PinCode1 {

    private final int PIN;

    public PinCode1(int pin) {
        PIN = pin;
    }

    public boolean confirmCode(int nubmer) {
        return this.PIN == nubmer;
    }
}
  • このPINコードがSystem.out.println(pc.PIN)ではアクセスできないことを確かめなさい
  • このPINコードをブルートフォースアタックで解読するコードを以下に書きなさい
  • なお、PINコードは整数4桁の数値 1000~9999 とする
package p11;

public class Q03 {

    public static void main(String[] args) {

        PinCode1 pc = new PinCode1(1234);

    //ここにコードを書く
        System.out.println(i);
    }
}

<出力結果>

1234

また、この仕様の場合、平均して何回の試行でPINが推測できるか手計算しなさい。

映画『ターミネーター2』のハッキングシーン

『ターミネーター2』では、主人公のジョン・コナーがATMをハッキングするシーンがあります。彼は、カードリーダーを使ってATMのシステムに侵入し(この部分は非現実的ですが)、4桁のPINコード(劇中では9003)を特定し、現金を引き出します。おそらく上記と同様のプログラムを使ったと推測されます。

力任せにすべての組み合わせを試すので、ブルートフォースアタックといいます。

4.PINコードのクラッキング防止

3.のインスタンスのPINコードを以下の対策で守りなさい。

・PinCode1クラスをコピーしPinCode2としこのクラスを使う

・試行回数(tryTimes)というフィールドを追加する

・試行回数が5回を超えたらシステムを強制終了する

・メインメソッドの構造には手を加えない

ヒント:System.exit(0);でシステムを強制終了させることができる。0は正常終了のコード。

<結果の例>

試行回数が5回を超えました。

5.PINコードジェネレータ

ワンタイムパスワードを生成するPINコードジェネレータを作成したい。

以下の条件を満たすように作成しなさい。

  • pinナンバーは他のクラスから直接アクセスできない
  • コンストラクタは同じパッケージからしかアクセスできない
  • セッターは用意しない
  • インスタンス生成時に桁数(digits)を指定する
  • 桁数は4~9までの整数とし、このルールに従わない場合にはインスタンス化されない

package p11;

public class Q05 {
    public static void main(String[] args) {
        PINGenerator pg = new PINGenerator(4);
        System.out.println(pg.getPin());
    }
}
class PINGenerator {
    //ここにコードを書く
}

<出力結果の例:実引数に4を与えた場合>

9757

6.クラスの責務

あなたがシステムエンジニをしている某国では、お店で商品を買った時に消費税がかかります。

消費税は2種類に分かれていてパン(bread)のような食品(Groceryクラス)は8%、鉛筆(pencil)のような食品以外の商品(NonGroceryクラス)は10%と決まっています。

そして現在の首相は消費税の見直しは今後5年間はしないことを公約に掲げて当選しました。

そこである新入社員が次のような税込金額を計算できるプログラムを作成しました。

ところが、現在の仕様では税率は、getPriceメソッドの引数で指定することになっています。

本来なら各々の商品の税率はどのクラスが知っているべき情報でしょうか?

package p11;

public class Q06 {
    public static void main(String[] args) {
        NonGrocery pencil = new NonGrocery("pen", 100);
        System.out.println(pencil.getPrice(0.1));
        Grocery bread = new Grocery("bread", 200);
        System.out.println(bread.getPrice(0.08));
    }
}

class Product {
    protected String name;
    protected int price;
    Product(String name, int price) {
        this.name = name;
        this.price = price;
    }
}
class Grocery extends Product {
    public Grocery(String name, int price) {
        super(name, price);
    }
    int getPrice(double taxRate) {
        return (int) Math.floor(this.price * (1.0 + taxRate));
    }
}

class NonGrocery extends Product {
    public NonGrocery(String name, int price) {
        super(name, price);
    }
    int getPrice(double taxRate) {
        return (int) Math.floor(this.price * (1.0 + taxRate));
    }
}

本来あるべきプログラムに修正しなさい。

7.オリジナル問題作成

将来の後輩のために良い問題が出来たら教えてください。

以上。

JavaSEの問題集トップページに戻る