zoukankan      html  css  js  c++  java
  • java 枚举类型使用总结

    注:阅读了effective java 讲诉enum的部分,做下笔记,下文中大部分代码来自effective java书中

    枚举类型是指由一组固定的常量组成的合法值得类型。

    使用枚举的好处:a,因为没有可以访问的构造器,枚举类型是真正的final;

            b,枚举类型提供类编译时的类型安全。如:函数中声明一个参数类型为枚举类型的Apple时,那么调用方法时传递到参数上的任何非null对象一定是Apple的值之一,         而是用静态常量就无法保证;

            c,包含同名常量的多个枚举类型可以和平共处,每个类型都有自己的命名空间

            d,枚举类型允许添加任意的方法和域,并可实现接口。

    1,常见的一组简单的枚举

    如:

    public enum Apple {
        FUJI,PIPPIN,CRANNY_SMITH
    }

    2,带有具体值的枚举(可自定义方法)

    public enum Apple {
        FUJI(1), PIPPIN(2), CRANNY_SMITH(3);
        
        private final int code;
        
        Apple(int code) {
            this.code = code;
        }
    
        public int getCode() {
            return code;
        }
    
        public static Apple fromCode(int code) {
            for (Apple apple : Apple.values()) {
                if (apple.getCode() == code)
                    return apple;
            }
            return null;
        }
    }

    3,多个参数,并带有运算方法

    public enum Planet {
    
        MERCURY(3.303e+23, 2.4397e6),
        VENUS(4.869e+24, 6.0518e6),
        EARTH(5.976e+24, 6.37814e6),
        MARS(6.421e+23, 3.3972e6),
        JUPITER(1.9e+27, 7.1492e7),
        SATURN(5.688e+26, 6.0268e7),
        URANUS(8.686e+25, 2.5559e7),
        NEPTUNE(1.024e+26, 2.4746e7),
        PLUTO(1.27e+22, 1.137e6);
        
        private final double mass;
    
        private final double radius;
    
        private final double surfaceGravity;// m/ s^2
    
        public static final double G = 6.67300E-11;
    
        Planet(double mass, double radius) {
            this.mass = mass;
            this.radius = radius;
            surfaceGravity = G * mass / (radius * radius);
        }
    
        public double mass() {
            return mass;
        }
    
        public double radius() {
            return radius;
        }
    
        public double surfaceWeight(double otherMass) {
            return otherMass * surfaceGravity;
        }
    }

    4,根据不同的常量有不同的方法

      switch方法 ----不推荐(有可能新添加了常量却没有在switch中加入就悲剧了)

    public enum Operation {
        PLUS("+"),
        MINUS("-"),
        TIMES("*"),
        DIVIDE("/");
        
        private final String symbol;
        Operation(String symbol){
            this.symbol=symbol;
        }
        
        public String getSymbol() {
            return symbol;
        }
    
        double apply(double x,double y){
            switch(this){
            case PLUS:return x + y;
            case MINUS:return x - y;
            case TIMES:return x * y;
            case DIVIDE:return x / y;
            }
            throw new AssertionError("unknown operation: "+this);
        }

      推荐:constant-specific method implementation

    public enum Operation {
        PLUS("+") {
            public double apply(double x, double y) {
                return x + y;
            }
        },
        MINUS("-") {
            public double apply(double x, double y) {
                return x - y;
            }
        },
        TIMES("*") {
            public double apply(double x, double y) {
                return x * y;
            }
        },
        DIVIDE("/") {
            public double apply(double x, double y) {
                return x / y;
            }
        };
    
        private final String symbol;
    
        Operation(String symbol) {
            this.symbol = symbol;
        }
    
        public String getSymbol() {
            return symbol;
        }
    
        public abstract double apply(double x, double y);
    
    }

    5,策略枚举 strategy enum

    先来看一种情况:通过一周的工作时间来计算工资,工作时间8小时,额外算加班,周末工作也算加班

    首先我们可以使用switch来做,这样看起来十分简单

    public enum PayrollDay {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FIRDAY, SATURDAY, SUNDAY;
    
        private static final int HOURS_PER_SHIFT = 8;
    
        double pay(double hoursWorked, double payRate) {
            double basePay = hoursWorked * payRate;
            double overtimePay;
            switch (this) {
            case SATURDAY:
            case SUNDAY:
                overtimePay = hoursWorked * payRate * 2;
            default:
                overtimePay = hoursWorked <= HOURS_PER_SHIFT ? 0
                        : (hoursWorked - HOURS_PER_SHIFT) * payRate * 2;
                break;
            }
            return basePay + overtimePay;
        }
    }

    但是同样有可能出现上面提到不严谨的问题,当枚举常量增加时,switch可能忘记加入

    使用策略枚举时 如下:

    public enum PayrollDay {
        MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(
                PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), FIRDAY(PayType.WEEKDAY), SATURDAY(
                PayType.WEEKEND), SUNDAY(PayType.WEEKEND);
    
        private final PayType payType;
    
        PayrollDay(PayType payType) {
            this.payType = payType;
        }
    
        public PayType getPayType() {
            return payType;
        }
    
        double pay(double hoursWorked, double payRate) {
            return payType.pay(hoursWorked, payRate);
        }
    
        enum PayType {
            WEEKDAY {
                @Override
                double overtimePay(double hours, double payRate) {
                    return hours < HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT)
                            * payRate * 2;
                }
            },
            WEEKEND {
                @Override
                double overtimePay(double hours, double payRate) {
                    return hours * payRate * 2;
                }
            };
            private static final int HOURS_PER_SHIFT = 8;
    
            abstract double overtimePay(double hours, double payRate);
    
            double pay(double hoursWorked, double payRate) {
                double basePay = hoursWorked * payRate;
                return basePay + overtimePay(hoursWorked, payRate);
            }
        }
    }

    6,上面几个例子中都不推荐时间switch,那么什么时候使用呢

    枚举中的switch语句适用于给外部的枚举类型增加特定于常量的行为。如:上面例子中的operation 如果希望他有一个方法返回对应的逆运算

    public static Operation inverse(Operation op) {
            switch (op) {
            case PLUS:
                return Operation.MINUS;
            case MINUS:
                return Operation.PLUS;
            case TIMES:
                return Operation.DIVIDE;
            case DIVIDE:
                return Operation.TIMES;
            default:
                throw new AssertionError("unknown operation : " + op);
            }
        }
  • 相关阅读:
    Android 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/china2k/p/4067539.html
Copyright © 2011-2022 走看看