もしこのブログがお役に立ちましたら、次回のAmazonでのお買い物時に こちらのリンクから 購入していただけますと嬉しく思います。

2010年3月15日

JavaのGenericsへの要望

ずっと開発に関わっているあるJavaベースのWebアプリがあるのですが、数ヶ月前にJREが1.4から5.0にアップデートされました。
今まで1.4準拠の構文ばかり使ってきたのですが、そろそろ5.0以降の構文にも慣れていかないといけないなぁと思い、今日試してみました。
Genericsを意識して使ってみたのですが、「型引数」を指定できるのは確かにバグを減らす効果があると思います。
ただ、「型引数」の影響範囲がsetterやgetterの類だけなのはいただけません。
例えば、ちょっと長いですが以下のようなコードを書いた場合です。

/**
* 標準入力を一行ずつ読み込み、足し算を行う
*/
public static void main(String[] args) {
// Listに型引数としてIntegerを指定する
List<Integer> inputNumbers = new ArrayList<Integer>();

Scanner scanner = new Scanner(System.in);
// 標準入力を一行ずつ読み込む
while (scanner.hasNext()) {
String inputText = scanner.next();
// "exit"と入力されたら標準入力の読み込みを終了する
if ("exit".equals(inputText)) {
break;
}
try {
// 数字の入力の場合のみListに追加する
inputNumbers.add(Integer.parseInt(inputText));
} catch (NumberFormatException e) {
System.out.println("数字を入力してください");
}
}

// ListにString変数の追加を試みる
inputNumbers.add("1"); // ←コンパイルエラー

// ListにStringの"1"が含まれるかチェックする
if (inputNumbers.contains("1")) { // ←コンパイルが通る
System.out.println("文字列の1が入力されました"); // ←このコードが実行されることはあり得ない
}

// ListにIntegerの"1"が含まれるかチェックする
if (inputNumbers.contains(1)) {
System.out.println("数値の1が入力されました"); // ←このコードが実行されることはあり得る
}

int sum = 0;
for (int number : inputNumbers) {
sum += number;
}
System.out.println("合計値 : " + sum);
}


25行目はコンパイルエラーが出るにも関わらず、28行目のコードは問題ありません。
例えば稀な例かも知れませんが、DBから読み出した数値をString型のまま扱ってしまった場合に、ListやMapの存在チェックのメソッドにその変数を渡してもtrueが返らない、なんてことが考えられます。
もし上の例の28行目のような場面でコンパイルエラーが出ればそのようなバグは防げます。
調べたところJava6.0でも同じ仕様のようですので、今後のバージョンでどうなるか見守りたいです。

0 件のコメント:

コメントを投稿