java之类型安全的枚举

why

  枚举,顾名思义,就是一组可罗列的值,如四季春夏秋冬,方位东南西北,星期,月份等。在J2SE5.0 Tiger会出现之前,通常定义一个普通类或者抽象类,在类中定义一组public staic final 修饰的成员变量来表示这样的数据。

public abstract class Direction {
    public static final int EAST = 0;  //
    public static final int WEST = 1;  //西
    public static final int SOUTH = 2;  //
    public static final int NORTH = 3;  //
}

然后我们就能通过“类名.变量名“Direction.EAST的形式来使用这些常量。

  那么像这样定义有什么不好的地方呢?我就举个例子来说明,比如有一个方法,需要接收上述的参数,那方法的声明肯定就像这样 returnType methodName(int direction); 注意方法的参数是int型,即任何的int类型的值不限0、1、2、3都能够作为该方法的参数。为了避免意料之外的结果,必须限定参数的上限和下限,否则就容易误传入非正确的int值,编译器是检查不出这类错误的,全靠人为控制。另一方面,使用静态常量时候,常常不够直观,不看定义,谁也不知道0、1、2、3究竟表示什么,而且当有要罗列多少种方向的需求的时候,也不方便。

  J2SE5.0提供了解决上述问题的一种方式,即用关键字enum定义的枚举。它克服了静态常量表示法的不足,在编译的时候,编译器就能检查出非法的参数,并不需要设定程序的上下界,所以说枚举是类型安全的。而且通过它自带的方法,很容易罗列所表示的值,简单明了。

what

  那么枚举如何表示上述的方向呢?

public enum Direction{
    EAST,WEST,SOUTH,NORTH;
}

  上面代码就是java枚举的定义。枚举本质上还是一个类,是和class,interface,annotation是一个级别的,源文件编译之后还是一个字节码文件,表面上我们用关键字enum定义,看不出什么,实际上编译器帮我们完成了大部分的东西。可以通过反编译工具把字节码文件反编译过来,就能看到编译器做了什么事。

  所有枚举类型都继承自Enum,Enum是所有枚举类型的基类。这个继承是编译器帮我们完成的。 因为枚举已经继承了Enum,所以不能再继承别的类,可以实现接口。枚举的构造函数只能是private或者默认修饰符,所以在编译完成,究竟有哪些枚举实例已经固定了。

how

带构造函数的枚举,这个例子也说明枚举可以添加成员变量和方法

public enum Direction {
    EAST("东"), WEST("西"), SOUTH("南"), NORTH("北");

    private final String name;

    private Direction(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

实现接口的枚举

public enum Direction implements MyService {
    EAST, WEST, SOUTH, NORTH;

    public void doSomething() {
        System.out.println(this.name());
    }
}

interface MyService {
    public void doSomething();
}

枚举(重写父类方法)

public enum Direction {
    EAST {
        public void doSomething() {
            System.out.println("东");
        }
    },
    WEST {
        public void doSomething() {
            System.out.println("西");
        }
    },
    SOUTH {
        public void doSomething() {
            System.out.println("南");
        }
    },
    NORTH;

    public void doSomething() {
        System.out.println(this.name());
    }
}

枚举(实现抽象方法)

public enum Direction {
    EAST {
        @Override
        void doSomething() {
            System.out.println("east");
        }
    },
    WEST {
        @Override
        void doSomething() {
            System.out.println("west");
        }

    },
    SOUTH {
        @Override
        void doSomething() {
            System.out.println("south");
        }
    },
    NORTH {
        @Override
        void doSomething() {
            System.out.println("north");
        }
    };

    abstract void doSomething();
}

  枚举比较

Direction direction = Direction.EAST;
System.out.println(direction.compareTo(Direction.WEST));

// if语句中的使用
if (Direction.EAST == direction) {
    System.out.println("equal");
} else
    System.out.println("not equal");

// 可以用于switch语句
 switch (direction) {
    case WEST:
       System.out.println("west");
       break;
    case EAST:
        System.out.println("east");
        break;
    case SOUTH:
        System.out.println("south");
        break;
    case NORTH:
        System.out.println("north");
        break;
    default:
        System.out.println("default");
 }

  至于枚举类从父类继承来的方法,请自行查阅java api帮助文档。枚举的出现,也在java集合框架中添加了两个成员,EnumSet和EnumMap,即枚举集合和枚举映射。EnumSet是一个抽象类,里面定义了创建枚举集合的不同静态方法,具体的用法看api,与普通的set和map无异。

  如果想了解更多的内容,请看这篇文章http://www.iteye.com/topic/678381

 

posted on 2014-02-25 21:53  思、慧  阅读(880)  评论(0编辑  收藏  举报

导航