Zacard's Notes

java enum的妙用

java中的枚举,大家应该并不陌生。可enum的特性和用法,可能并不是很了解。enum的出现主要是为了代替public static final的常量的。因为常量有诸多的不便,包括没有命名空间,无法按组隔离,使用容易遗忘,扩展不便,没有编译时错误约束等。于是enum出现了,本文将介绍一些enum巧妙的用法。

enum的特点

enum具有以下特点:

  • 单例,java中实现单例最快捷的方式

  • 本质上是一个final类,并且继承java.lang.Enum

  • 可以在switch判断语句上使用enum,但是并不推荐

  • 可以设置具体的枚举值

利用抽象类构造符合开闭原则的代码

当我们使用enum的时候,大部分人会用switch语句做判断而实现不同枚举使用不用的逻辑。例如以下一个计算器操作的例子:

    /**
     * 计算器操作枚举
     *
      * @author zacard
      * @since 2015-12-14 10:17
      */
    public enum Operation {
        PLUS("+"),
        MINUS("-"),
        MULTIPLY("*"),
        DIVISION("/");

        private String symbol;

        Operation(String symbol) {
            this.symbol = symbol;
        }

        @Override
        public String toString() {
            return symbol;
        }
    }


    /**
     * 测试
     *
      * @author zacard
      * @since 2015-12-14 10:12
      */
    public class MyTest {

    // 计算
    public int apply(Operation operation, int x, int y) {
        int result;
        switch (operation) {
            case PLUS:
                result = x + y;
                break;
            case MINUS:
                result = x - y;
                break;
            case MULTIPLY:
                result = x * y;
                break;
            case DIVISION:
                result = x / y;
                break;
            default:
                result = 0;
                break;
        }
        return result;
    }
}

这是一个很常见的例子,但是确有极大的隐患。比如计算器操作类增加一个枚举:RADICAL(“√ ̄”)根号,很多客户端的代码就需要改,而且很容易遗忘,因为没有编译时错误的约束。并且大量的switch case语句使得代码冗余,更不符合开闭原则。

只需要对枚举类稍加改造,增加一个抽象方法,即可改变以上种种的问题,代码如下:

/**
 * 计算器操作枚举
 *
  * @author zacard
  * @since 2015-12-14 10:17
  */
public enum Operation {
    PLUS("+") {
        @Override
        public int apply(int x, int y) {
            return x + y;
        }
    },
    MINUS("-") {
        @Override
        public int apply(int x, int y) {
            return x - y;
        }
    },
    MULTIPLY("*") {
        @Override
        public int apply(int x, int y) {
            return x * y;
        }
    },
    DIVISION("/") {
        @Override
        public int apply(int x, int y) {
            return x / y;
        }
    },
    // 新增加的操作,开根号
    RADICAL("√ ̄") {
        @Override
        public int apply(int x, int y) {
            return (int) Math.sqrt(x);
        }
    };

    private String symbol;

    Operation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }

    // 计算
    public abstract int apply(int x, int y);
}

/**
 * 测试
 *
  * @author zacard
  * @since 2015-12-14 10:12
  */
public class MyTest {

    // 计算
    public int apply(Operation operation, int x, int y) {
        return operation.apply(x, y);
    }
}

当定义了一个抽象方法apply的时候,枚举必须实现这个抽象方法,不然会编译报错,不会造成新增加一个枚举而造成逻辑遗漏的问题。同时,客户端调用的代码页变得异常简单和优雅。

利用接口实现可伸缩的枚举类

我们知道枚举本质是继承Enum的类,并且java是单继承的。因此我们可以使用接口,让枚举实现接口,来构建可伸缩的枚举类,代码如下:

/**
 * 计算器操作动作
 *
 * @author Guoqw
 * @since 2015-12-14 13:09
 */
public interface Action {

    // 计算
    int apply(int x, int y);
}


/**
 * @author Guoqw
 * @since 2015-12-14 10:17
 */
public enum Operation implements Action {
    PLUS("+") {
        @Override
        public int apply(int x, int y) {
            return x + y;
        }
    },
    MINUS("-") {
        @Override
        public int apply(int x, int y) {
            return x - y;
        }
    },
    MULTIPLY("*") {
        @Override
        public int apply(int x, int y) {
            return x * y;
        }
    },
    DIVISION("/") {
        @Override
        public int apply(int x, int y) {
            return x / y;
        }
    },
    RADICAL("√ ̄") {
        @Override
        public int apply(int x, int y) {
            return (int) Math.sqrt(x);
        }
    };

    private String symbol;

    Operation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }
}

这样的好处是当我们要扩充计算器操作枚举类是,来的很方便,代码如下:

/**
 * 计算器操作扩展类
 *
 * @author Guoqw
 * @since 2015-12-14 13:13
 */
public enum ExtendOperation implements Action {
    // 倒数
    RECIPROCAL("1/x") {
        @Override
        public int apply(int x, int y) {
            return 1 / x;
        }
    };

    private String symbol;

    ExtendOperation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }
}        
坚持原创技术分享,您的支持将鼓励我继续创作!

热评文章