SwitchでStringを!?

今まで、JavaではStringを判定するときに色々苦労した。
一番ダサいやり方は以下の様にコードを書いている。

public class SwitchToStringJavaSE6 {
    /**
     * Stringの分岐は今までこうだった。はず。。。
     */
    public static void main(String[] args){
        String target = "TRUE";

        // "TRUE"を判定する
        if ("FALSE".equals(target)) {
            System.out.println("FALSE");
       } else if ("DEFAULT".equals(target)) {
            System.out.println("DEFAULT");
       } else if ("TRUE".equals(target)) {
            System.out.println(target);
       } else {
            System.out.println("NOTARGET");
       }
    }
}

これで”TRUE”を判定し、”TRUE”と表示していた。
しかし、JavaSE7ではなんとSwitchでStringも使えるようになった。。。
ウソだろ。。。

public class SwitchToStringJavaSE7 {
    /**
     * JavaSE7のステキなSwitch文
     */
    public static void main(String[] args) {
        String target = "TRUE";
        // Switch文でStringを判定する。
         switch(target) {
            case "FALSE":
                System.out.println("FALSE");
                break;
            case "DEFAULT":
                System.out.println("DEFAULT");
                break;
            case "TRUE":
                System.out.println(target);
                break;
            default:
                System.out.println("NOTARGET");
                break;
         }
    }
}

これで”TRUE”が表示される。

これって・・・。
新人がよく間違えるSwitch文じゃないかしら・・・。
StringはSwitch使えないんだよ!って教えられた気がする。

どういう原理????
JavaSE6で書くと、こういうことらしい。

public class SwitchToStringJavaSE6Reproduce {
    /**
     * JavaSE6でJavaSE7のSwitchを再現する。
     */
    public static void main(String[] args) {

        String target = "TRUE";
        // ハッシュコード判定用
        int hash = -1;

        switch (target.hashCode()) {
        // ハッシュコードの確認を行う。
        case 66658563:
            // "FALSE"のハッシュコード
            if ("FALSE".equals(target)) {
                // ハッシュコードが同じ文字列を考慮
                hash = 0;
            }
            break;

        case -2032180703:
            // "DEFAULT"のハッシュコード
            if ("DEFAULT".equals(target)) {
                // ハッシュコードが同じ文字列を考慮
                hash = 1;
            }
            break;
        case 2583950:
            // "TRUE"のハッシュコード
            if ("TRUE".equals(target)) {
                // ハッシュコードが同じ文字列を考慮
                hash = 2;
            }
            break;

        }
        // 判定後の処理をさらに記載する。
        switch (hash) {
        
        case 0:
            System.out.println("FALSE");
            break;
        case 1:
            System.out.println("DEFAULT");
            break;
        case 2:
            System.out.println("TRUE");
            break;
        default:
            System.out.println("NOTARGET");
        }
    }
}

なるほど。こういう手があったか。。。
でも、これは自動コンパイルの中で実施してもらわないと、やっぱり使えないな。。。
というわけで、JavaSE7は上記のようなめんどくさいことをやってくれるおかげでSwitch文でStringが使えるわけだ。

ありがとう。JavaSE7。

ちなみに、問題もある。

switch(null) { // コンパイルエラー
case null;  // コンパイルエラー
    // 省略
}

じゃあ、これはどうだ。

String target = null;
switch(target) {  // NullPointerExceptionが発生
case "TEST":
    // 省略
}

null.hashCode()を実施してNullPointerExceptionが発生する。
ということは、StringのSwitch文の前には必ずnullチェックを付けたほうが良いみたい。

使い方はそれぞれだが、凄く活用できそうな拡張であることがわかった。