一、枚举类型——使用接口来组织枚举

枚举类型无法被继承,这一点可能有时会让人沮丧。想要继承枚举的动机,一部分源自希望扩充原始枚举中的元素,另一部分源自想要使用子类型来创建不同的子分组。

你可以在一个接口内对元素进行分组,然后基于这个接口生成一个枚举,通过这样的方式来实现元素的分类。举个例子,假如你有一些类型互不相同的 food (食物),想创建若干 enum 来组织它们,但又希望它们仍然是 Food 类型,你可以这么做:

Food.java

public interface Food {
    enum Appetizer implements Food {
        SALAD, SOUP, SPRING_ROLLS;
    }

    enum MainCourse implements Food {
        LASAGNE, BURRITO, PAD_THAI,
        LENTILS, HUMMUS, VINDALOO;
    }

    enum Dessert implements Food {
        TIRAMISU, GELATO, BLACK_FOREST_CAKE,
        FRUIT, CREME_CARAMEL;
    }

    enum Coffee implements Food {
        BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
        LATTE, CAPPUCCINO, TEA, HERB_TEA;
    }
}

实现接口是唯一可子类化枚举的方式,因此所有嵌套在 Food 中的枚举类型都实现了 Food 接口。现在我们基本可以说“ 一切都是某种类型的Food”,如下例所示:

TypeOfFood.JAVA

import enums.TEST0522.Food.*;

public class TypeOfFood {
    public static void main(String[] args) {
        Food food = Appetizer.SALAD;
        food = MainCourse.LASAGNE;
        food = Dessert.GELATO;
        food = Coffee.CAPPUCCINO;
    }
}

对于每个实现了 Food 接口的枚举类型,都可以向上转型为 Food ,因此它们全都是 Food 类型 。

但是,当你要处理一组类型时,接口往往就不如枚举有用。如果要创建“由枚举组成的枚举”,你可以为 Food 中的每个枚举类型都创建一个外部枚挙类型:

Course.java

public enum Course {
    APPETIZER(Food.Appetizer.class),
    MAINCOURSE(Food.MainCourse.class),
    DESSERT(Food.Dessert.class),
    COFFEE(Food.Coffee.class);
    private Food[] values;

    private Course(Class<? extends Food> kind) {
        values = kind.getEnumConstants();
    }

    public Food randomSelection() {
        return Enums.random(values);
    }
}

上面的代码中,每个枚举类型都接收相应的 Class 对象以作为构造参数,从而可以使用 getEnumConstants() 来提取出所有的枚举实例并存储起来,这些实例稍后会在 randomselection() 中被用到。好了,现在我们可以从每个 Course (菜项,如“ 前菜/主菜/ 甜点”)中选择一种 Food (食物),生成一份随机配好的午餐了。

Meal.java

public class Meal {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            for (Course course : Course.values()) {
                Food food = course.randomSelection();
                System.out.println(food);
            }
            System.out.println("***");
        }
    }
}

运行结果如下:
在这里插入图片描述

此处,创建一个由枚举类型组成的枚举类型的意义在于,可以方便地遍历每个 Course。在稍后的例子 VendingMachine.java 中,你会看到另一种由不同约束条件指定的分类方法。

另一种更简洁的分类方法是在枚举内嵌套枚举,如下例所示:

SecurityCategory.java

enum SecurityCategory {
    STOCK(Security.Stock.class),
    BOND(Security.Bond.class);
    Security[] values;

    SecurityCategory(Class<? extends Security> kind) {
        values = kind.getEnumConstants();
    }

    interface Security {
        enum Stock implements Security {
            SHORT, LONG, MARGIN
        }

        enum Bond implements Security {
            MUNICIPAL, JUNK
        }
    }

    public Security randomSelection() {
        return Enums.random(values);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            SecurityCategory category = Enums.random(SecurityCategory.class);
            System.out.println(category + ": " + category.randomSelection());
        }
    }
}

运行结果如下:
在这里插入图片描述

Security接口用于将内部的枚举类型作为公共类型聚合到一起,然后再将它们归类到
SecurityCategory 中的枚举中。

如果将此方法应用到前面的Food示例,那么结果如下:

Meal2.java

public enum Meal2 {
    APPETIZER(Food.Appetizer.class),
    MAINCOURSE(Food.MainCourse.class),
    DESSERT(Food.Dessert.class),
    COFFEE(Food.Coffee.class);
    private Food[] values;

    private Meal2(Class<? extends Food> kind) {
        values = kind.getEnumConstants();
    }

    public interface Food {
        enum Appetizer implements Food {
            SALAD, SOUP, SPRING_ROLLS;
        }

        enum MainCourse implements Food {
            LASAGNE, BURRITO, PAD_THAI,
            LENTILS, HUMMUS, VINDALOO;
        }

        enum Dessert implements Food {
            TIRAMISU, GELATO, BLACK_FOREST_CAKE,
            FRUIT, CREME_CARAMEL;
        }

        enum Coffee implements Food {
            BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
            LATTE, CAPPUCCINO, TEA, HERB_TEA;
        }
    }

    public Food randomSelection() {
        return Enums.random(values);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            for (Meal2 meal : Meal2.values()) {
                Food food = meal.randomSelection();
                System.out.println(food);
            }
            System.out.println("***");
        }
    }
}

运行结果如下:
在这里插入图片描述

最后,虽然这只是对代码重新组织了一下,但在某些情况下,这样可以使结构更加清晰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在JDK1.5 之前,我们定义常量都是: publicstaticfianl.... 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。 public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。 enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color = Signal.RED; public void change() { switch (color) { case RED: color = Signal.GREEN; break ; case YELLOW: color = Signal.RED; break ; case GREEN: color = Signal.YELLOW; break ; } } } 用法三:向枚举中添加新方法 如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum实例。 public enum Color { RED("红色" , 1 ), GREEN( "绿色" , 2 ), BLANK( "白色" , 3 ), YELLO( "黄色" , 4 ); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this .name = name; this .index = index; } // 普通方法 public static String getName( int index) { for (Color c : Color.values()) { if (c.getIndex() == index) { return c.name; } } return null ; } // get set 方法 public String getName() { return name; } public void setName(String name) { this .name = name; } public int getIndex() { return index; } public void setIndex( int index) { this .index = index; } } 用法四:覆盖枚举的方法 下面给出一个toString()方法覆盖的例子。 public enum Color { RED("红色" , 1 ), GREEN( "绿色" , 2 ), BLANK( "白色" , 3 ), YELLO( "黄色" , 4 ); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this .name = name; this .index = index; } //覆盖方法 @Override public String toString() { return this .index+ "_" + this .name; } } 用法五:实现接口 所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。 public interface Behaviour { void print(); String getInfo(); } public enum Color implements Behaviour{ RED("红色" , 1 ), GREEN( "绿色" , 2 ), BLANK( "白色" , 3 ), YELLO( "黄色" , 4 ); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this .name = name; this .index = index; } //接口方法 @Override public String getInfo() { return this .name; } //接口方法 @Override public void print() { System.out.println(this .index+ ":" + this .name); } } 用法六:使用接口组织枚举 public interface Food { enum Coffee implements Food{ BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO } enum Dessert implements Food{ FRUIT, CAKE, GELATO } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小熊猫呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值