はじめに
Javaのswitch文ではenumを式にしてした場合、修飾名を付与しないというのがあります。
2つ以上同じ定数があった場合にコンパイルが通ったのが不思議だったので調べてみました。
結果から先にいうと、修飾は不要なので気にせずにそのまま使って大丈夫です。
enumが1つの場合
こういうenumがあるとします。
FoodType.java
public enum FoodType {
RICE,
BREAD,
OTHER,
}
Main.java
import lombok.AllArgsConstructor;
public class Main {
public static void main(String[] args) {
Food food = new Food(FoodType.RICE);
switch (food.foodType){
case RICE:
System.out.println("ごはんだよ");
break;
case BREAD:
System.out.println("パンだよ");
break;
default:
System.out.println("その他だよ");
break;
}
}
}
@AllArgsConstructor
class Food {
FoodType foodType;
}
Mainの方でswitch文でenum(FoodType)を分岐させています。
この場合、caseをFoodType.RICE
ではなくRICE
と書きます。
(なぜRICEでよいのかというのは後述します。)
enumが2つの場合
先ほどのコードにenumを1つ追加してみます。
ごはんの区分をさらに細かく分けたい場合を想定。
RiceType
public enum RiceType {
RICE,
FriedRice,
}
Mainも変更。
Main.java
import lombok.AllArgsConstructor;
public class Main {
public static void main(String[] args) {
Food food = new Food(FoodType.RICE,RiceType.RICE);
switch (food.foodType){
case RICE:
switch (food.riceType){
case RICE:
System.out.println("ごはんだよ");
break;
case FriedRice:
System.out.println("チャーハンだよ");
break;
}
break;
case BREAD:
System.out.println("パンだよ");
break;
default:
System.out.println("その他だよ");
break;
}
}
}
@AllArgsConstructor
class Food {
FoodType foodType;
RiceType riceType;
}
なぜ名前が衝突しないのか
上記のコードでコンパイルは通ります。
これは正しいコードですが、Mainの以下の箇所でcase RICE:
とcase RICE:
が衝突しないでコンパイルが通ることに疑問を持ちました。
また、コードはすべて載せているのでimportは使用されていません。
switch (food.foodType){
case RICE:
switch (food.riceType){
case RICE:
コンパイル時に修飾してくれている
調べたところ、コンパイル時にクラス名が修飾されるようになっているため、名前は衝突しないようです。
少し古いですが、以下のサイトの「switchの実装」の項にenumの逆コンパイルの結果が紹介されています。
http://www.ne.jp/asahi/hishidama/home/tech/java/enum.html#h2_switch
まとめ
コンパイル時に修飾される仕組みでした。