java中枚举优先使用

java 1.5之后出现枚举类型,枚举类型的出现为开发者提供类型安全的检测和提高可读性;当然枚举的使用有一个缺点就是相比于int定义的标志位,装载和初始化枚举时会有空间和时间成本;所以除了小型终端,实践中不必太在意这个问题;

1.int枚举模式和String枚举模式的局限性:

1.1 int枚举
  • 在java开发中,经常会使用常量来定义一些标志位之类的情况;比如在下面程序中,使用int来记录状态:
    ......
    public static final int Apple_FUJI = 0;
    public static final int Apple_PIPPN = 1;
    public static final int Apple_BLOOD = 2;
    public static final int Orange_FUJI = 3;
    public static final int Orange_PIPPN = 4;
    public static final int Orange_BLOOD = 5;
    ......
  • 1 .使用int是脆弱的,int枚举是编译时常量用final修饰,当int常量发生变化时候,若要达到预期效果必须重新编译(final 只能初始化一次)

  • 2 .使用int是不友好的,int只能获取相应的int值,不能打印所表示的常量的字符串,code的阅读性是不高的,换句话说不提供文档你甚至不知道怎么命名,怎么赋值;

  • 3 .使用int常量的命名是有限制的,在使用int的时候要严格避免重名,而且你无法获取int常量的size;

1.2 String枚举

用String来记录标志位,和int其实差不多,但也有所不同:

  • 优点: 可以打印出想要得到的字符串名,其他一无是处

  • 缺点: String的比较不能直接使用’==’,必须使用equals(),会影响性能

1.3 String枚举

对比与int等基本数据类型以及String,他除了装载和初始化枚举时会有空间和时间成本之外,可以完美解决前两者的所有隐患;

  • 1 .枚举是线性安全的:枚举类型是真正的final,客户端既不能创建枚举的实例,也不能扩展枚举;
public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    /**
     * The name of this enum constant, as declared in the enum declaration.
     * Most programmers should use the {@link #toString} method rather than
     * accessing this field.
     */
    private final String name;

    /**
     * Returns the name of this enum constant, exactly as declared in its
     * enum declaration.
     *
     * <b>Most programmers should use the {@link #toString} method in
     * preference to this one, as the toString method may return
     * a more user-friendly name.</b>  This method is designed primarily for
     * use in specialized situations where correctness depends on getting the
     * exact name, which will not vary from release to release.
     *
     * @return the name of this enum constant
     */
    public final String name() {
        return name;
    }
   ......

枚举类继承了 Comparable, Serializable,而且都是final不可变的修饰,不会出现线程不安全的问题;

  • 2.枚举是编译时的安全类型;比如定义一个Apple的enum,那么当其作为参数时候,只能传入Apple下定义的枚举实例,不然会编译时报错,提高开发效率;
  • 3.包含同名常量的多个枚举类型可以在一个系统中共处;因为枚举中每个类型都有他自己的命名空间;
  • 4.你可以重新排列或增加枚举类型中的常量而不需要重新编译;因为导出常量的域在枚举类型和他的客户端之间存在一个隔离层:枚举并没有编译到客户端代码中,而是存储在int枚举之中,然后通过toString然后转换成可打印的字符串;

2.枚举中添加任意方法和域

在枚举中不仅可以存储枚举常量,还可以存储任意方法和域,但是继续强调一点,枚举可以继承接口,但是枚举本身不可以扩展;
下面来看一下代码:

public enum Opration {
    PLUS,DIVIDE;
    public double apply(double x,double y){
        switch (this){
            case PLUS:
                return x + y;
            case DIVIDE:
                return x - y;
        }
        throw new AssertionError("unkown");
    }

}

这是一个实现加减法的enum,声明了两个枚举常量:PLUS,DIVIDE;注意:

枚举中常量是可以与方法关联的,也就是说PLUS和DIVIDE可以调用Opration中任意方法,当然包括其构造;

但是出于一个合格的java开发者,上面代码是不符合java开闭原则的,当要在Opration中添加其他枚举常量还必须在switch中添加case:
那么我们下面来优化代码:

public enum Opration {


    PLUS("+") {
        @Override
        public double apply(double x, double y) {
            return x+y;
        }
    },
    DIVIDE("-"){
        @Override
        public double apply(double x, double y) {
            return x-y;
        }
    };

    private final String sym;

    Opration(String sym) {
        this.sym = sym;
    }


    public abstract double apply(double x,double y)

}

这样当添加一种运算方式时候,只需要单独实现其抽象apply就ok了,不用太多关注apply中的switch;

感谢阅读,欢迎pick!!!

猜你喜欢

转载自blog.csdn.net/soullines/article/details/80762062