java中的枚举类型详解

1、 基本特性
2、 向enum中添加新方法
3、 switch语句中的enum
4、values()详解
5、随机选取(实例)
6、使用接口组织枚举
7、枚举的枚举

1、 基本特征

方法摘要

int compareTo(E o) Enum类实现了Comparable接口

boolean equals(Object oher) 编译器为你提供了equals()和hashCode()方法

class<E> getDeclaringClass()

String name() 返回enum实例声明时的名字,与使用toString()效果相同

int ordinal() 返回enum实例在声明时的顺序,从0开始

static<T extens Enum<T>> valueOf(class<T> enumType,String name) 根据名字返回enum实例

package enumTest;

enum Shrubbery{GROUND,CRAWLING,HANGING}

public class EnumClsaa {
    public static void main(String[] args) {
        for(Shrubbery s:Shrubbery.values()){
            System.out.println(s+" ordinary: "+s.ordinal());
            System.out.print(s.compareTo(Shrubbery.CRAWLING)+" ");
            System.out.print(s.equals(Shrubbery.CRAWLING)+" ");
            System.out.println(s==Shrubbery.CRAWLING);
            System.out.println(s.getDeclaringClass());
            System.out.println(s.name());
        }
        //根据名字返回enum实例
        for(String s:"HANGING CRAWLING GROUND".split(" ")){
            Shrubbery shrub=Enum.valueOf(Shrubbery.class,s);
            System.out.println(shrub);
        }
    }
}

//output
GROUND ordinary: 0
-1 false false
class enumTest.Shrubbery
GROUND
CRAWLING ordinary: 1
0 true true
class enumTest.Shrubbery
CRAWLING
HANGING ordinary: 2
1 false false
class enumTest.Shrubbery
HANGING
HANGING
CRAWLING
GROUND

2、向enum中添加新方法

因为enum类都继承自Enum,因此,除了不能继承自enum之外,基本上可以将enum看做一个常规的类。

package enumTest;

public enum OzWitch {
    //实例必须最先定义
    WEST("WEST INSTANTCE"),
    NORTH("NORTH INSTANCE"),
    EAST("EAST INSTANCE"),
    SOUTH("SOUTN INSTANCE");
    private String description;
    //如果打算自定义方法,则必须在enum实例序列的最后添加一个分号
    private OzWitch(String description){
        this.description=description;
    }
    public String getDescription(){
        return this.description;
    }

    public static void main(String[] args) {
        for(OzWitch witch:OzWitch.values()){
            System.out.println(witch+" : "+witch.getDescription());
        }
    }
}

//output
WEST : WEST INSTANTCE
NORTH : NORTH INSTANCE
EAST : EAST INSTANCE
SOUTH : SOUTN INSTANCE
  • 注意
    此例中,将构造器声明为private,但对于它(构造器)的可访问性而言,并没有任何变化,因为(即使不声明为private)我们只能在enum定义的内部使用其构造器创建enum实例,一旦enum的定义结束,编译器就不允许我们再使用其构造器来创建任何实例了。

常见的应用:建立数据字典

package com.cwy.enums;

/**
 * 表示秒杀状态的数据字典
 */
public enum SeckillStatEnum {
    SUCCESS(1,"秒杀成功"),
    END(0,"秒杀结束"),
    REPEAT_KILL(-1,"重复秒杀"),
    INNER_ERROR(-2,"系统异常"),
    DATE_REWRITE(-3,"数据篡改");

    private int state;
    private String info;

    SeckillStatEnum(int state, String info) {
        this.state = state;
        this.info = info;
    }

    public int getState() {
        return state;
    }


    public String getInfo() {
        return info;
    }


    public static SeckillStatEnum stateOf(int index)
    {
        for (SeckillStatEnum state : values())
        {
            if (state.getState()==index)
            {
                return state;
            }
        }
        return null;
    }
}

3、 switch语句中的enum

package enumTest;

enum Signal{GREEN,YELLOW,RED}

/**
 * 小型状态机实例
 * (此例:交通灯的转换)
 */
public class TrafficLight {
    Signal color=Signal.RED;
    public void change(){
        switch (color){
            //注意这儿不能写成case Signal.RED
            case RED:
                color=Signal.GREEN;
                break;
            case GREEN:
                color=Signal.YELLOW;
                break;
            case YELLOW:
                color=Signal.RED;
                break;
        }
    }
    //覆盖toString()方法
    public String toString(){
        return "The traffic light is "+color;
    }

    public static void main(String[] args) {
        TrafficLight trafficLight=new TrafficLight();
        for(int i=0;i<7;i++){
            System.out.println(trafficLight);
            trafficLight.change();
        }
    }
}

//output
The traffic light is RED
The traffic light is GREEN
The traffic light is YELLOW
The traffic light is RED
The traffic light is GREEN
The traffic light is YELLOW
The traffic light is RED

4、values()详解

注意,对于Enum类而言,本身没有values()方法,但是自己创建的enum类(都会继承Enum)却有values()方法

package enumTest;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.TreeSet;

enum Explore{HERE,THERE}

/**
 * 分析values()
 */
public class Reflection {
    public static Set<String> analyze(Class<?> enumClass){
        System.out.println("----- Analyzing "+enumClass+" -----");
        System.out.println("Interfaces:");
        for(Type t:enumClass.getGenericInterfaces()){
            System.out.println(t);
        }
        System.out.println("Base:"+enumClass.getSuperclass());
        System.out.println("Method:");
        Set<String> methods=new TreeSet<String>();
        for(Method method:enumClass.getMethods()){
            methods.add(method.getName());
            System.out.print(method.getName()+" ");
        }
        System.out.println();
        return methods;
    }

    public static void main(String[] args) {
        Set<String> exploreMethods=analyze(Explore.class);
        Set<String> enumMethods=analyze(Enum.class);
        System.out.println("Explore.containsAll(Enum)? "+exploreMethods.containsAll(enumMethods));
        System.out.println("Explore.removeAll(enumMethods)");
        exploreMethods.removeAll(enumMethods);
        System.out.println(exploreMethods);
    }
}

//output
----- Analyzing class enumTest.Explore -----
Interfaces:
Base:class java.lang.Enum
Method:
values valueOf name equals toString hashCode compareTo compareTo valueOf getDeclaringClass ordinal wait wait wait getClass notify notifyAll 
----- Analyzing class java.lang.Enum -----
Interfaces:
java.lang.Comparable<E>
interface java.io.Serializable
Base:class java.lang.Object
Method:
name equals toString hashCode compareTo compareTo valueOf getDeclaringClass ordinal wait wait wait getClass notify notifyAll 
Explore.containsAll(Enum)? true
Explore.removeAll(enumMethods)
[values]
  • 因此,values()是编译器添加的static方法,并且,在创造Explore时其实还添加了valuesOf(String name)方法。原生Enum的valueOf需要两个参数(具体见最上面),而Explore只需要一个。
  • 由于values()方法是由编译器插入到enum定义中的static方法,所以,将enum实例向上转化为Enum,那么values()方法就不可以访问了。不过,在Class中有一个getEnumConstants()方法,所以即使Enum接口中没有values()方法,我们仍可以通过Class对象取得所有enum实例。
package enumTest;

enum Search{HITHER,YOU}

/**
 * getEnumConstants()测试
 */
public class UpcastEnum {
    public static void main(String[] args) {
        Search[] vals=Search.values();
        //向上转换
        Enum e=Search.HITHER;
        //此时,e.values();无效
        for(Enum en:e.getClass().getEnumConstants()){
            System.out.println(en);
        }
    }
}

//output
HITHER
YOU

5、随机选取(实例)

package enumTest;

import java.util.Random;

/**
 * 利用泛型,从enum实例中随机选取
 */
public class Enums {
    private static Random rand=new Random(50);
    public static <T extends Enum<T>> T random(Class<T> ec){
        return random(ec.getEnumConstants());
    }
    public static <T> T random(T[] values){
        return values[rand.nextInt(values.length)];
    }
}

enum Activity{SITTING,LYING,STADING,RUNNING,JUMPING,FLYING}

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

//output
LYING
SITTING
FLYING
JUMPING
LYING
LYING
JUMPING
SITTING
SITTING
JUMPING

6、使用接口组织枚举

package enumTest;

/**
 * 使用接口组织枚举
 */
public interface Food {
    enum Appetizer implements Food{
        SALAD,SOUP,SPRING_ROLLS
    }
    enum MainCourse implements Food{
        LASAGNE,BURRITO,PAD_THAI
    }
    enum Dessert implements Food{
        FRUIT,CAKE
    }
}
class TypeOfFood{
    public static void main(String[] args) {
        Food food= Food.Appetizer.SALAD;
            food= Food.MainCourse.LASAGNE;
            food= Food.Dessert.CAKE;
    }
}
  • 由此例可知,当enum类型实现了Food接口,那么就可以将其实例向上转化为Food。但是,当需要与很多类型打交道时,接口就不如enum好用。例如,可以创建枚举的枚举。

7、枚举的枚举

1)实现方式一

package enumTest;

/**
 * 将enum的每个实例包装Food中的每一个enums类,
 * 即可形成“枚举的枚举”
 */
public enum Course {
    APPETIZER(Food.Appetizer.class),
    MAINCOURSE(Food.MainCourse.class),
    DESSERT(Food.Dessert.class);
    private Food[] values;
    private Course(Class<? extends Food> kind){
        values=kind.getEnumConstants();
    }
    public Food randomSelection(){
        return Enums.random(values);
    }
}

应用实例

package enumTest;

/**
 * 利用:“枚举的枚举”,随机生成菜单
 */
public class Meal {
    public static void main(String[] args) {
        for(int i=0;i<5;i++){
            for(Course c:Course.values()){
                Food food=c.randomSelection();
                System.out.println(food);
            }
            System.out.println("--------");
        }
    }
}

//output
--------
SOUP
LASAGNE
CAKE
--------
SOUP
PAD_THAI
CAKE
--------
SALAD
PAD_THAI
FRUIT
--------

2)实现方式二

枚举的嵌套

package enumTest;

/**
 * 管理枚举更简洁的方法:
 * 将一个enum嵌套在另一个enum内
 */
public enum SecurityCategory {
    STOCK(Security.Stock.class),
    BOND(Security.Bond.class);
    private 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());
        }
    }
}

//output
BOND :  JUNK
BOND :  JUNK
BOND :  MUNICIPAL
BOND :  JUNK
BOND :  JUNK
BOND :  JUNK
STOCK :  MARGIN
STOCK :  SHORT
BOND :  MUNICIPAL
BOND :  JUNK
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值