前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java枚举用法整理

Java枚举用法整理

作者头像
孟君
发布2019-11-12 16:09:17
1.4K0
发布2019-11-12 16:09:17
举报
文章被收录于专栏:孟君的编程札记

在项目中,一般推荐使用枚举来代替常量接口和常量类。但是,枚举类的用途不仅仅是定义常量,还有其它较多的方法,比如:实现接口定义抽象方法当作单例使用等。

本文是对Java枚举使用方法的一个整理,并给出示例。在JDK 1.5之前,定义常量,我们一般使用两种方式:

  • 定义一个常量类
  • 定义一个常量接口

定义常量类,如:

代码语言:javascript
复制
/** * @author wangmengjun */public class SeasonConstants {
    public static final int SPRING = 0;    public static final int SUMMER = 1;    public static final int FALL = 2;    public static final int WINTER = 3;}

定义常量接口,如:

代码语言:javascript
复制
/** * @author wangmengjun */public interface SeasonInterface {
    public static final int SPRING = 0;    public static final int SUMMER = 1;    public static final int FALL = 2;    public static final int WINTER = 3;}

这样一来,凡是实现SeasonInterface接口的类都会自动继承这些常量。如:

代码语言:javascript
复制
public class Main implements SeasonInterface {
    public static void main(String[] args) {        int season = SPRING;    }}

Java枚举类在JDK 1.5引入的,枚举类在项目中已经不可或缺。

正是因为Java枚举类可以有自定义的方法,可以实现接口、定义抽象类等,更加的灵活,已经被广大开发人员推荐在项目中使用 -- 使用枚举类替换接口常量或者类常量等。

接下来,我们一起来看一些使用枚举的示例:

一、Java枚举类使用

声明枚举的语法如下:

代码语言:javascript
复制
public/protected/private] enum Enum_name {
  ... ...}

1.1 无构造函数的枚举

我们可以定义一个Season的枚举,包含四个季节,如:

代码语言:javascript
复制
/** * @author wangmengjun */public enum Season {
    SPRING,    SUMMER,    FALL,    WINTER}

每个枚举类的常量是 public、static、final修饰的。

可以结合switch来使用,如:

代码语言:javascript
复制
public class Main {
    public static void main(String[] args) {        Season season = Season.SPRING;        switch (season) {            case SPRING:                System.out.println("Spring ~~~");                break;            case SUMMER:                System.out.println("Summer ~~~");                break;            case FALL:                System.out.println("Fall ~~~");                break;            case WINTER:                System.out.println("Winter ~~~");                break;            default:                break;        }    }}

1.2 有构造函数的枚举

构造函数中的参数可以一个或者多个。

  • 一个参数的构造函数示例

比如,美国硬币的种类,可以添加一个币值作为参数,如:

代码语言:javascript
复制
public enum Coin {
    PENNY(1),    NICKEL(5),    DIME(10),    QUARTER(25); //US coins
    private int value;
    private Coin(int value) {        this.value = value;    }
    public int getValue() {        return value;    }}

使用示例:

代码语言:javascript
复制
int coidValue = Coin.NICKEL.getValue(); //  5
  • 多个参数的构造函数示例:

有时候,我们需要不止一个参数,如一个产品类型的枚举类,可以包含2个参数,一个int值,一个String值,分别用于存入数据库的值和页面显示的值。如:

代码语言:javascript
复制
public enum ProductType {
    SMART_HOME(0, "智能家居"),    HEALTH_CARE(1, "医疗健康"),    MOTION_DETECTION(2, "运动检测"),    INDUSTRIAL_PRODUCTION(3, "工业生产"),    ENVIRONMENT_MONITORING(4, "环境监测"),    INTELLIGENT_OFFICE(6, "智能办公"),    LOCATION_DEVICE(7, "定位器/防丢器"),    SMART_GATEWAY(8, "智能网关"),    OTHERS(5, "其它");
    private int code;
    private String name;
    private ProductType(int code, String name) {        this.code = code;        this.name = name;    }
    /**     * @return the code     */    public int getCode() {        return code;    }
    /**     * @return the name     */    public String getName() {        return name;    }

}

这种情况,比较适合页面上下拉框选项的场景,如使用JSTL来循环一下传给页面的枚举类集:

代码语言:javascript
复制
<select class="form-control" id="J_pro_type" name="productType"    data-change="click">    <option value="">请选择产品类型</option>      <c:forEach items="${types}" var="type">       <option value="${type.code }"> ${type.name}</option>    </c:forEach>
</select>

下拉框效果图如下:

1.3 获取枚举类中所有常量

可以通过枚举类的values() 方法获取指定枚举的常量数组,如:

代码语言:javascript
复制
        Coin[] coins = Coin.values();
        for (Coin coin : coins) {            System.out.println(String.format("%s --> value is %d", coin.name(), coin.getValue()));        }

输出结果:

代码语言:javascript
复制
PENNY --> value is 1NICKEL --> value is 5DIME --> value is 10QUARTER --> value is 25

1.4 包含自定义方法

我们可以在Coin枚举类中,添加一个自定的方法,比

代码语言:javascript
复制
    public boolean isPenny() {        return this == PENNY;    }

修改后的Coin.java内容如下:

代码语言:javascript
复制
public enum Coin {
    PENNY(1),    NICKEL(5),    DIME(10),    QUARTER(25); //US coins
    private int value;
    private Coin(int value) {        this.value = value;    }
    public boolean isPenny() {        return this == PENNY;    }
    public int getValue() {        return value;    }
}

这样,我们就能通过isPenny方法知道该Coin对象是否为PENNY。

代码语言:javascript
复制
      Coin penny = Coin.PENNY;       System.out.println(penny.isPenny());//true
       Coin dime = Coin.DIME;       System.out.println(dime.isPenny());//false

1.5 实现接口

定义一个接口Next,包含nextSeason方法,用于输出下一个季节是什么。

代码语言:javascript
复制
public interface Next {    void nextSeason();}

修改Season枚举内容:

代码语言:javascript
复制
/** * @author wangmengjun */public enum Season implements Next {
    SPRING,    SUMMER,    FALL,    WINTER;
    @Override    public void nextSeason() {        switch (this) {            case SPRING:                System.out.println("Next season is Summer");                break;            case SUMMER:                System.out.println("Next season is Fall");                break;            case FALL:                System.out.println("Next season is Winter");                break;            case WINTER:                System.out.println("Next season is Spring");                break;            default:                break;        }
    }}

测试一下:

代码语言:javascript
复制
      Season spring = Season.SPRING;      spring.nextSeason();//输出Next season is Summer

1.6 包含抽象方法

除了可以实现接口外,枚举类还可以包含抽象方法

代码语言:javascript
复制
/** * @author wangmengjun */public enum RegularExpressionEnum {
    NUMERIC("^[0-9]+$") {        @Override        public boolean match(String value) {            return Pattern.matches(this.getRegPattern(), value);        }    },
    ALPHABETIC("^[a-zA-Z]+$") {        @Override        public boolean match(String value) {            return Pattern.matches(this.getRegPattern(), value);        }    };
    private String regPattern;
    private RegularExpressionEnum(String regPattern) {        this.regPattern = regPattern;    }
    /**     * @return the regPattern     */    public String getRegPattern() {        return regPattern;    }
    public abstract boolean match(String value);
}

示例:

代码语言:javascript
复制
        RegularExpressionEnum numeric = RegularExpressionEnum.NUMERIC;        System.out.println(numeric.match("123"));//true        System.out.println(numeric.match("1a2"));//false
        RegularExpressionEnum alphabetic = RegularExpressionEnum.ALPHABETIC;        System.out.println(alphabetic.match("123"));//false        System.out.println(alphabetic.match("abc"));//true

如何选择,是选择实现接口或者使用抽象方法呢?

如果一个方法,每个枚举常量的方法实现都是一样的那么最好使用接口,不用抽象方法。实现接口,只要在枚举中实现一个接口方法即可;使用抽象方法,每个枚举中的常量都需要实现一遍抽象方法。 如果每个常量的行为各异,变化大,那么使用抽象方法来做,较为合适。

比如,将上述抽象方法的例子,改成实现接口的方式,一起来看一下代码的变化。

代码语言:javascript
复制
public interface RegularExpressionInterface {
    boolean match(String value);}

RegularExpressionEnum修改如下:

代码语言:javascript
复制
/** * @author wangmengjun */public enum RegularExpressionEnum implements RegularExpressionInterface {
    NUMERIC("^[0-9]+$"),    ALPHABETIC("^[a-zA-Z]+$");
    private String regPattern;
    private RegularExpressionEnum(String regPattern) {        this.regPattern = regPattern;    }
    /**     * @return the regPattern     */    public String getRegPattern() {        return regPattern;    }
    @Override    public boolean match(String value) {        return Pattern.matches(this.getRegPattern(), value);    }}

测试代码和结果和上述抽象方法的一样。

代码语言:javascript
复制
        RegularExpressionEnum numeric = RegularExpressionEnum.NUMERIC;        System.out.println(numeric.match("123"));//true        System.out.println(numeric.match("1a2"));//false
        RegularExpressionEnum alphabetic = RegularExpressionEnum.ALPHABETIC;        System.out.println(alphabetic.match("123"));//false        System.out.println(alphabetic.match("abc"));//true

1.7 作为单例使用

代码语言:javascript
复制
public enum Attendant {
    INSTANCE;
    private Attendant() {        // perform some initialization routine    }
    public void sayHello() {        System.out.println("Hello!");    }}

public class Main {
    public static void main(String[] args) {        Attendant.INSTANCE.sayHello();// instantiated at this point    }}

1.8 包含静态变量和静态方法

以上面说过的产品类型(ProductType)枚举为例,int值存在数据库中,但是,需要在页面上根据int值显示对应的产品详细类型,这个时候我们可以在枚举类中添加一个Map, 然后添加一个静态方法getNameByCode,来实现,如:

代码语言:javascript
复制
    private static final Map<Integer, ProductType> MAP = new HashMap<>();
    static {        for (ProductType type : ProductType.values()) {            MAP.put(type.getCode(), type);        }    }
代码语言:javascript
复制
    public static String getTypeNameByCode(int code) {        if (MAP.containsKey(code)) {            return MAP.get(code).getName();        }        return "";    }

完整的ProductType枚举内容如下:

代码语言:javascript
复制
import java.util.HashMap;import java.util.Map;
public enum ProductType {
    SMART_HOME(0, "智能家居"),    HEALTH_CARE(1, "医疗健康"),    MOTION_DETECTION(2, "运动检测"),    INDUSTRIAL_PRODUCTION(3, "工业生产"),    ENVIRONMENT_MONITORING(4, "环境监测"),    INTELLIGENT_OFFICE(6, "智能办公"),    LOCATION_DEVICE(7, "定位器/防丢器"),    SMART_GATEWAY(8, "智能网关"),    OTHERS(5, "其它");
    private int code;
    private String name;
    private static final Map<Integer, ProductType> MAP = new HashMap<>();
    static {        for (ProductType type : ProductType.values()) {            MAP.put(type.getCode(), type);        }    }
    private ProductType(int code, String name) {        this.code = code;        this.name = name;    }

    /**     *      * @param code     * @return     */    public static String getTypeNameByCode(int code) {        if (MAP.containsKey(code)) {            return MAP.get(code).getName();        }        return "";    }
    /**     * @return the code     */    public int getCode() {        return code;    }

    /**     * @return the name     */    public String getName() {        return name;    }
}

这样一来,如果获取一个产品对象,其type为1,那么直接可以通过1获取对应的产品类型名称为医疗健康。可以设置到VO中,用于展示。

代码语言:javascript
复制
    String name = ProductType.getTypeNameByCode(1);    System.out.println(name);//医疗健康

大家如果对枚举类的使用,还有其它使用方法也请留言给出,大家一起学习分享~~ :)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Java枚举类使用
    • 1.1 无构造函数的枚举
      • 1.2 有构造函数的枚举
        • 1.3 获取枚举类中所有常量
          • 1.4 包含自定义方法
            • 1.5 实现接口
              • 1.6 包含抽象方法
                • 1.8 包含静态变量和静态方法
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档