【JAVA基础——优雅的Enum枚举】Java 枚举(enum) 如何编写一个优雅的枚举,枚举的用法.枚举的继承与实现.


前言

enum 的一些小小编码建议,以及扩展知识(开发中可能会用到)


存在问题的Enum示例

public enum Operation {

    PLUS("+","加法"),
    MINUS("-","减法"),
    TIMES("*","乘法"),
    DIVIDE("/","除法"),
    NULL("",""),
    
    ;
    //符号
    private String symbol;
    
    private String display;


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

    public String getSymbol() {
        return symbol;
    }

    public String getDisplay() {
        return display;
    }
    
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    
    @Override
    public String toString() {
        return "Operation{" +
                "symbol='" + symbol + '\'' +
                '}';
    }

    public static Operation getBySymbol(String symbol) {
        for (Operation value : values()) {
            if (value.getSymbol().equals(symbol)) {
                return value;
            }
        }
        return NULL;
    }
-
}

class Main{
    public static void main(String[] args) {
        Operation en = Operation.getBySymbol("+");
        System.out.println("en = " + en);
        en.setSymbol("-");
        System.out.println("en = " + en);
    }
}

输出

en = Operation{symbol='+'}
en = Operation{symbol='-'}

虽然不太会有人如此做,但可以造成枚举值被改变,这显然对于枚举的定义来说是错误的!

示例 Enum 优化

    1. 属性 final,使不可变
    1. lombok 的 枚举(简化写法)
    1. 优化每次get循环的getBySymbol方法
@Getter
@ToString
@AllArgsConstructor
public enum Operation {


    PLUS("+", "加法"),

    MINUS("-", "减法"),

    TIMES("*", "乘法"),

    DIVIDE("/", "除法"),

    NULL("", ""),

    ;
    //符号
    private final String symbol;

    private final String display;

    @Deprecated
    public static Operation getBySymbolOld(String symbol) {
        for (Operation value : values()) {
            if (value.getSymbol().equals(symbol)) {
                return value;
            }
        }
        return NULL;
    }

    private static final Map<String, Operation> enumMap = new HashMap<>();

    static {
        for (Operation op : Operation.values()) {
            enumMap.put(op.toString(), op);
        }
    }

    public static Operation getBySymbol(String symbol) {
        return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
    }
}

其他 enum 知识扩展

    1. 枚举不能继承 ,enum 默认继承了 java.lang.Enum 类(反编译)
	public final class Operation extends Enum{
	    ... ...
	}
    1. 枚举可以使用抽象方法参数,枚举项必须实现,可以借此实现策略模式.不同枚举定义不同的策略行为.
@Getter
@ToString
@AllArgsConstructor
public enum Operation {

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

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

    TIMES("*") {
        @Override
        public double apply(double x, double y) {
            return x * y;
        }
    },

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

    NULL("") {
        @Override
        double apply(double x, double y) {
            return 0;
        }
    },
    ;
    private final String symbol;

    /**
     * 抽象方法,枚举项必须 override
     */
    abstract double apply(double x, double y);
    /**
     * 默认实现,所有枚举都使用,也可以 override
     */
//    double apply(double x, double y) {
//        throw new RuntimeException("");
//    }

    private static final Map<String, Operation> enumMap = new HashMap<String, Operation>();

    static {
        for (Operation op : Operation.values()) {
            enumMap.put(op.symbol, op);
        }
    }

    public static Operation getBySymbol(String symbol) {
        return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
    }

}

    1. 枚举可以实现接口,类似枚举内方法.

需要每个 枚举项都实现接口方法,若接口方法为 default 的,则,枚举项可以使用接口的默认返回值;

public interface Calculator {
    double apply(double x, double y);
    
    /**
     * 接口默认方法,实现类可以不重写
     */
//    default double apply(double x, double y) {
//        return 0.0;
//    }
}

@Getter
@AllArgsConstructor
public enum Operation implements Calculator {

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

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

    TIMES("*") {
        @Override
        public double apply(double x, double y) {
            return x * y;
        }
    },

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

    NULL("") {
        @Override
        public double apply(double x, double y) {
            throw new RuntimeException("错误");
        }
    },
    ;
    private final String symbol;

    private static final Map<String, Operation> enumMap = new HashMap<String, Operation>();

    static {
        for (Operation op : Operation.values()) {
            enumMap.put(op.symbol, op);
        }
    }

    public static Operation getBySymbol(String symbol) {
        return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
    }
}

可以在枚举类内重写,类似接口实现默认方法,

@Getter
@AllArgsConstructor
public enum Operation implements Calculator {

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

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

    TIMES("*") {
        @Override
        public double apply(double x, double y) {
            return x * y;
        }
    },

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

    NULL(""),
    ;
    private final String symbol;

    @Override
    public double apply(double x, double y) {
        throw new RuntimeException("错误");
    }

    private static final Map<String, Operation> enumMap = new HashMap<String, Operation>();

    static {
        for (Operation op : Operation.values()) {
            enumMap.put(op.symbol, op);
        }
    }

    public static Operation getBySymbol(String symbol) {
        return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
    }
}

总结

启发于 《Effective Java第二版》,作者Joshua Bloch是Sun公司的高级工程师,也是“Java平台核心组”的设计师。书中指明了在写Java代码时兼顾可维护性与效率的方式,有非常专业的理论知识,强烈推荐。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值