博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java枚举用法整理
阅读量:6799 次
发布时间:2019-06-26

本文共 9031 字,大约阅读时间需要 30 分钟。

hot3.png

在项目中,一般推荐使用枚举来代替常量接口和常量类。

但是,枚举类的用途不仅仅是定义常量,还有其它较多的方法,比如:实现接口定义抽象方法当作单例使用等。

本文是对Java枚举使用方法的一个整理,并给出示例。

在JDK 1.5之前,定义常量,我们一般使用两种方式:

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

定义常量类,如:

/** * @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;}

定义常量接口,如:

/** * @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接口的类都会自动继承这些常量

如:

public class Main implements SeasonInterface {    public static void main(String[] args) {        int season = SPRING;    }}

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

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

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

Java枚举类使用

声明枚举的语法如下:

[public/protected/private] enum Enum_name {... ...}

无构造函数的枚举

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

/** * @author wangmengjun */public enum Season {    SPRING,    SUMMER,    FALL,    WINTER}

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

可以结合switch来使用,如:

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;        }    }}

有构造函数的枚举

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

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

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

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;    }}

使用示例:

int coidValue = Coin.NICKEL.getValue(); //  5
  • 多个参数的构造函数示例:

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

如:

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来循环一下传给页面的枚举类集:

下拉框效果图如下:

134044_ISyw_2911530.png

获取枚举类中所有常量

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

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

输出结果:

PENNY --> value is 1NICKEL --> value is 5DIME --> value is 10QUARTER --> value is 25

包含自定义方法

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

public boolean isPenny() {        return this == PENNY;    }

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

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。

Coin penny = Coin.PENNY;       System.out.println(penny.isPenny());//true              Coin dime = Coin.DIME;       System.out.println(dime.isPenny());//false

实现接口

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

public interface Next {    void nextSeason();}

修改Season枚举内容:

/** * @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;        }    }}

测试一下:

Season spring = Season.SPRING;      spring.nextSeason();//输出Next season is Summer

包含抽象方法

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

/** * @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);}

示例:

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

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

如果一个方法,每个枚举常量的方法实现都是一样的那么最好使用接口,不用抽象方法。实现接口,只要在枚举中实现一个接口方法即可;使用抽象方法,每个枚举中的常量都需要实现一遍抽象方法。

如果每个常量的行为各异,变化大,那么使用抽象方法来做,较为合适。

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

public interface RegularExpressionInterface {    boolean match(String value);}

RegularExpressionEnum修改如下:

/** * @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);    }}

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

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

作为单例使用

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    }}

包含静态变量和静态方法

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

private static final Map
MAP = new HashMap<>(); static { for (ProductType type : ProductType.values()) { MAP.put(type.getCode(), type); } }

 

public static String getTypeNameByCode(int code) {        if (MAP.containsKey(code)) {            return MAP.get(code).getName();        }        return "";    }

完整的ProductType枚举内容如下:

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
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中,用于展示。

String name = ProductType.getTypeNameByCode(1);		System.out.println(name);//医疗健康

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

转载于:https://my.oschina.net/wangmengjun/blog/827189

你可能感兴趣的文章
[ Nowcoder Contest 167 #C ] 部分和
查看>>
MFC 中CFileDialog的用法
查看>>
关于SVM一篇比较全介绍的博文
查看>>
English - because of,due to ,thanks to ,owing to ,as a result of ,on account of解析
查看>>
全球免费开放的电子图书馆
查看>>
27_Blog Reader
查看>>
个人代码库のC#可移动按钮“相关代码”
查看>>
MyBatis配置项--配置环境(environments)--databaseIdProvider
查看>>
类、对象、方法、实例方法、类方法
查看>>
《CLR via C#》读书笔记 之 目录导航
查看>>
51Nod 1009:1009 数字1的数量 (思维)
查看>>
Spring下载地址
查看>>
SQL性能优化总结
查看>>
WinHex数据恢复笔记(二)
查看>>
c#设计模式系列:观察者模式(Observer Pattern)
查看>>
NO23 Linux正则表达式结合三剑客企业级实践--取IP
查看>>
Max user processes limits
查看>>
Memcached 总结
查看>>
python 帮助和导入路径
查看>>
java连接oracle数据库(利用MyEclipse开发工具反向生成 bean与配置文件)
查看>>