拡張性/柔軟性を獲得する章

3.9. データの入れ物として使わない

『目的』

文字列は「テキスト」を表現するために設計されています。
むやみにデータの入れ物として使うのはやめましょう。

『Before』

まず、文字列を「値型」の代わりとして使うことを考えてみます。

たとえば、タブ区切りテキストファイルから読み込んだデータは、 意味として数値であろうが日付であろうが文字列の形式で読み込まれます。

このようなイメージですね。

name  money drunkard birthDay
いしだ 10000 いいえ  1980/12/15

それぞれのデータをStringとして扱ってみます。

// 金額
String money = "10000";

金額の足し引きをしたいときにとても面倒ですよね。

// 大酒飲みか否か
String drunkard = "いいえ";

大酒飲みか否か判定したいときに面倒ですね。

// 誕生日
String birthDay = "1977/12/9";

日付に関する処理をしたいときに面倒そうですね。

次に、文字列を「列挙型」の代わりとして使うことを考えてみます。

このようなイメージですね。

public class PlayingCard {
    public static final String CLUBS = "clubs";
    public static final String DIAMONDS = "diamonds";
    public static final String HEARTS = "hearts";
    public static final String SPADES = "spades";
        :
}

CLUBSやHEARTSを使用した比較処理では、文字列の比較(内部的には一文字づつ charで比較される)に依存するので、パフォーマンスの面で損をしてしまいます。 また、値をそのままハードコーディングされてしまう危険性があります。 スペルミスによる誤りを誘発しかねません。

setPlayingCard("clabs"); // 間違い

次に、文字列を「集合型」の代わりとして使うことを考えてみます。

このような感じです。

String compundKey = className + "#" + i.next();

フィールドを区切る文字(#)がフィールドのどれか一つに含まれていたら破綻しますね。 個々のフィールドにアクセスするには文字列の解析が必要になってしまいます。 間違いを起こしやすいし、処理も遅いです。

『After』

データにとって適切な型を使いましょう。

// 金額
BigDecimal money = new BigDecimal(10000L);

// 大酒飲みか否か
boolean drunkard = false;

// 誕生日
String birthDay = Calender.getInstance().set(1977, 11, 9);

文字列を使わずに「列挙型(enum)」を使用します。

public enum PlayingCard {
    CLUBS,
    DIAMONDS,
    HEARTS,
    SPADES,
        :
}

※「列挙型の定義」を参照してください。

Set<String> set = new HashSet<>();

set.add("aaa");
set.add("bbb");

『まとめ』

文字列は他の「値型」に対する代替としては貧弱です。
文字列は「列挙型」に対する代替としては貧弱です。
文字列は「集合型」に対する代替としては貧弱です。

< 前のページへ

Pagetop