JAVA之枚举Enum

一、什么是枚举?

Java 中的枚举(Enum)是一种特殊的类类型,它允许你定义一组常量。枚举提供了一种类型安全的方式来组织一组相关的常量。

**************************************************************************************************************

二、枚举的一些关键特性

1.类型安全枚举提供了编译时类型检查,确保使用枚举的地方只能是预定义的枚举常量之一。

2.固定数量的实例:枚举类型定义了一组固定数量的实例,这些实例在枚举类中显式声明。

3.单例模式:每个枚举常量都是单例的,Java 虚拟机(JVM)只为每个枚举常量创建一个实例。

4.继承 java.lang.Enum:所有枚举类型隐式地继承java.lang.Enum 类,这意味着它们共享一些公共行为。

5.可以有构造函数:枚举类型可以有自己的构造函数,用于初始化枚举常量的状态。

6.可以有成员变量和方法:枚举类型可以包含成员变量和方法,这些可以是静态的也可以是非静态的。

7.可以实现接口:枚举类型可以实现一个或多个接口,这使得枚举类型可以具有更复杂的行为。

8.可以有抽象方法:枚举类型可以包含抽象方法,每个枚举常量必须提供这些抽象方法的具体实现。

9.序列化:枚举类型是可序列化的,这意味着它们可以被写入到文件或通过网络传输。

10.命名空间:枚举类型提供了一个命名空间,使得常量的名称可以在整个程序中唯一。

11.迭代:枚举类型可以被迭代,例如使用 for-each 循环。

12.values()方法:枚举类型有一个静态方法 values(),返回枚举常量的数组。

13.valueOf()方法:Enum 类提供了 valueOf() 静态方法,可以根据名称获取枚举常量。

14.ordinal()方法:每个枚举常量都有一个与之关联的序数,可以通过 ordinal() 方法获取。

**************************************************************************************************************

三、枚举使用场景

1.定义一组固定常量:当需要一组固定的常量值时,使用枚举可以确保这些值不会被修改,提供类型安全和可读性。

2.控制方法参数:当方法需要一个参数,该参数只能是几个预定义的值之一时,使用枚举可以限制参数的取值范围。

3.实现单例模式:枚举本身是单例的,每个枚举常量在 JVM 中只有一个实例,这可以用来实现全局访问点或单例模式。

4.状态机:枚举可以用来表示有限状态机的状态,每个枚举值代表一个状态。

5.配置文件:枚举可以用于配置文件中,表示配置项的选项,例如数据库连接的类型。

6.开关/选项:在需要开关或选项的地方,枚举可以提供一组预定义的选项。

7.与switch语句配合使用:枚举常量可以与switch语句配合使用,实现多条件分支。

8.实现接口:枚举可以实现接口,这允许枚举常量具有方法和行为。

9.注解的参数:枚举常量可以作为注解的参数,提供一组预定义的选项。

10.资源管理:枚举可以用来管理资源,例如数据库连接池中的连接状态。

11.日志级别:枚举可以定义日志级别,如DEBUG、INFO、WARN、ERROR。

12.方向和方位:枚举可以用来表示方向,如NORTH、SOUTH、EAST、WEST。

13.星期和月份:枚举可以表示星期的天或月份,提供类型安全和易于维护的代码。

14.颜色和尺寸:在需要表示颜色或尺寸的地方,枚举可以提供一组预定义的值。

15.策略模式:枚举可以用来实现策略模式,每个枚举常量代表一个策略。

**************************************************************************************************************

四、枚举与常量类

常量通常放置在接口中,程序可以直接使用,并且常量不能被修改,因为在接口中定义的常量时,常量的修饰符通常为final与static。如:

interface Color{
    public static final int YELLOW = 1;
    public static final int WHITE = 2;
    public static final int GREEN = 3;
    public static final int BLUE = 4;
    public static final int RED = 5;
}

枚举与常量类的区别:

枚举类常量类
单例完全单例、线程安全。不单例
枚举类编译后类为:public final class T extends Enum,不允许继承可防止被子类修改。常量类可被继承修改、增加字段等,容易导致父类的不兼容。
性能性能高。性能低
常量值地址唯一,可以用==直接对比使用常量类时,往往得通过equals去判断两者是否相等。
引用类不需重新编译引用类。需要重新编译引用类。
枚举类编译时,没有把常量值编译到代码里,即使常量的值发生变化,也不会影响引用常量的类。常量类编译时,是直接把常量的值编译到类的二进制代码里,常量的值在升级中变化后,需要重新编译引用常量的类,因为里面存的是旧值。
越界不会越界。可能越界。
编译期间限定类型,不允许发生越界的情况。switch语句支持枚举型,当switch使用intString类型时,由于值的不稳定性往往会有越界的现象,对于这个的处理往往只能通过if条件筛选以及default模块来处理。
五、枚举与普通类 

没什么差别,枚举也可以定义变量与方法:

public class Test {
    public static void main(String[] args) {
        ColorEnum.RED.setColorName("非红色");
        System.out.println(ColorEnum.RED.getColorName());
        System.out.println(ColorEnum.RED.getDescription());
    }
}

enum ColorEnum {
    YELLOW("黄色"),
    WHITE("白色"),
    GREEN("绿色"),
    BLUE("蓝色"),
    RED("红色");
    
    //这个必须定义,且成员变量的类型及个数必须对应于上边枚举的定义
    //枚举标识码(英文描述)
    private final String description;
    private String colorName;
    
    //必须提供为私有的,防止外部new对象
    ColorEnum(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
    
    public String getColorName() {
        return colorName;
    }

    public void setColorName(String colorName) {
        this.colorName = colorName;
    }
}
执行结果:
非红色
红色

六、枚举与数据库

枚举型可以直接与数据库打交道,通常使用varchar类型存储,对应的是枚举项的名字。

在下边的例子中,如果某个类中的字段为:private ColorEnum color; 则其对应的数据库中的值为:"YELOW"、"RED"、"BLUE"、"GREEN"、"WHITE"。

enum ColorEnum {
    YELLOW("黄色"),
    WHITE("白色"),
    GREEN("绿色"),
    BLUE("蓝色"),
    RED("红色");
    
    //这个必须定义,且成员变量的类型及个数必须对应于上边枚举的定义
    //枚举标识码(中文描述)
    private final String description;

    //枚举标识码(对应颜色)
    private String colorName;
    
    ColorEnum(String description) {
        this.description = description;
    }
    
    //必须提供为私有的,防止外部new对象
    public String getDescription() {
        return description;
    }
    
    public String getColorName() {
        return colorName;
    }

    public void setColorName(String colorName) {
        this.colorName = colorName;
    }
}
七、单个参数示例:(类似普通类中得构造参数)
public class Test {
    public static void main(String[] args) {
        for (ColorEnum color: ColorEnum.values()) {
            System.out.println("color name:"+color.name() +"->" + "color desc:"+color.getDescription());
        }
    }
}

enum ColorEnum {
    YELLOW("黄色"),
    WHITE("白色"),
    GREEN("绿色"),
    BLUE("蓝色"),
    RED("红色");

    //这个必须定义,且成员变量的类型及个数必须对应于上边枚举的定义
    //枚举标识码(中文描述)
    private final String description;

    //枚举标识码(对应颜色)
    private String colorName;
    
    //必须提供为私有的,防止外部new对象
    ColorEnum(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

执行结果:
color name:YELLOW->color desc:黄色
color name:WHITE->color desc:白色
color name:GREEN->color desc:绿色
color name:BLUE->color desc:蓝色
color name:RED->color desc:红色
八、多个参数:(类似普通类中得构造参数)
public class Test {
    public static void main(String[] args) {
        System.out.println("根据英文描述获取中文描述:" + ColorEnum.getDescriptionByCode(ColorEnum.YELLOW.getCode()));
        System.out.println("根据输入字符获取中文描述(有):" + ColorEnum.getDescriptionByCode("RED"));
        System.out.println("根据输入字符获取中文描述(无):" + ColorEnum.getDescriptionByCode("PURPLE"));
    }
}

enum ColorEnum {
    YELLOW("YELLOW", "黄色"),
    WHITE("WHITE", "白色"),
    GREEN("GREEN", "绿色"),
    BLUE("BLUE", "蓝色"),
    RED("RED", "红色");

    //枚举标识码(中文描述)
    private final String description;

    //这个必须定义,且成员变量的类型及个数必须对应于上边枚举的定义
    //枚举标识码(英文描述)
    private final String code;

    ColorEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }

    public String getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }

    public static String getDescriptionByCode(String code) {
        for (ColorEnum value : ColorEnum.values()) {
            if (value.getCode().equals(code)) {
                return value.getDescription();
            }
        }
        return null;
    }
}

执行结果:
根据英文描述获取中文描述:黄色
根据输入字符获取中文描述(有):红色
根据输入字符获取中文描述(无):null
九、异常处理应用

异常码枚举:

package enums.expection;
 
import org.apache.commons.lang.StringUtils;
 
public enum ErrorCodeEnum {
    SYS_ERROR(1001, "系统错误,请重试"),
    UNKNOWN_ERROR(1002, "未知的系统异常"),
    SERVICE_INVOKE_FAIL(1003, "服务调用失败"),
    ILLEGAL_ARGS(1004, "参数校验错误"),
    ;
    
 
    /**
     * 结果码值
     */
    private final Integer code;
    
    /**
     * 描述
     */
    private final String description;
 
    ErrorCodeEnum(Integer code, String description) {
        this.code = code;
        this.description = description;
    }
 
    public static ErrorCodeEnum getByValue(String code) {
        for (ErrorCodeEnum result : values()) {
            System.out.println(result.ordinal());
            if (StringUtils.equals(result.getCode(), code)) {
                return result;
            }
        }
        return null;
    }
 
    public Integer getCode() {
        return code;
    }
 
    public String getDescription() {
        return description;
    }
 
}

自定义异常:

package enums.expection;
 
import org.apache.commons.lang.StringUtils;
 
import java.util.HashMap;
import java.util.Map;
 
public  class WangException extends RuntimeException {
 
    /** 错误码枚举*/
    private ErrorCodeEnum errorCode;
 
    /**
     * 详细错误信息
     */
    private Map<String, String> errorMap = new HashMap<String, String>();
 
    /**
     * 带参构造器
     */
    public WangException(ErrorCodeEnum errorCode) {
        super(errorCode.getDesc());
        this.setErrorCode(errorCode);
    }
 
    /**
     * 带参构造器.
     */
    public WangException(ErrorCodeEnum errorCode, String message) {
        super(StringUtils.isNotBlank(message) ? message : errorCode.getDesc());
        this.setErrorCode(errorCode);
    }
 
    /**
     * 带参构造器
     */
    public WangException(ErrorCodeEnum errorCode, Map<String, String> errorMap) {
        this(errorCode);
        this.errorMap = errorMap;
    }
    /**
     * 带参构造器
     */
    public WangException(String message) {
        super(message);
        this.setErrorCode(ErrorCodeEnum.UNKNOWN_ERROR);
    }
 
    /**
     * Gets error code.
     */
    public ErrorCodeEnum getErrorCode() {
        return errorCode;
    }
    
    /**
     * Sets error code.
     */
    public void setErrorCode(ErrorCodeEnum errorCode) {
        this.errorCode = errorCode;
    }
    /**
     * Gets error map.
     */
    public Map<String, String> getErrorMap() {
        return errorMap;
    }
    
    /**
     * Sets error map.
     */
    public void setErrorMap(Map<String, String> errorMap) {
        this.errorMap = errorMap;
    }
 
    private static String findMessage(Map<String, String> errorMap) {
        if (errorMap.isEmpty()) {
            return null;
        }
        return errorMap.values().iterator().next();
    }
 
}

测试:

public class Test {

    public static void main(String[] args) {
        String name = "";
        int i = 0;
        try {
            if (name == null)
                throw new WangException(ErrorCodeEnum.ILLEGAL_ARGS);
            if (i == 0)
                throw new WangException(ErrorCodeEnum.ILLEGAL_ARGS, "参数不能为0");
        } catch (WangException e) {
            e.printStackTrace();
            System.out.println("异常码:" + e.getErrorCode().getCode());
            System.out.println("异常描述:" + e.getMessage());
        }
    }
}
十、高级操作

接口中定义注解:

interface Color {
    enum Green {LIGHT_GREEN, DARK_GREEN}

    enum Red {LIGHT_RED, DARK_RED}
}

public class Demo {
    public static void main(String[] args) {
        System.out.println(Color.Green.DARK_GREEN.ordinal());
    }
}

执行结果:
1
十一、枚举上使用注解

注解类

/**
 * 指定颜色的父颜色(所属颜色)
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@interface Parent {
    Color[] value() default {};
}
/**
 * 表示是最底层的(即:没有子层)
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@interface Bottom {
    String name() default "";
}

枚举类:


import com.alibaba.nacos.shaded.org.checkerframework.common.subtyping.qual.Bottom;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

enum MyColor {
    RED,
    
    @Parent({RED})
    LIGHT_RED,

    @Bottom(name = "深红色")
    @Parent({RED, LIGHT_RED})
    DARK_RED;

    static List<MyColor> bottoms = new ArrayList<>();

    List<MyColor> children = new ArrayList<>();

    static {
        for (MyColor value : MyColor.values()) {
            try {
                Field field = MyColor.class.getField(value.name());
                if (field.isAnnotationPresent(Bottom.class)) {
                    bottoms.add(value);
                }

                Parent parent = field.getAnnotation(Parent.class);
                if (parent != null) {
                    for (MyColor myColor : parent.value()) {
                        myColor.children.add(value);
                    }
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
    }
}

测试类:

public class Test{
    public static void main(String[] args) {
        System.out.println("MyColor.RED.children:         " + MyColor.RED.children);
        System.out.println("MyColor.LIGHT_RED.children:   " + MyColor.LIGHT_RED.children);
        System.out.println("MyColor.bottoms:              " + MyColor.bottoms);

        try {
            Field field = MyColor.class.getField(MyColor.DARK_RED.name());
            if (field.isAnnotationPresent(Bottom.class)) {
                System.out.println("MyColor.DARK_RED的注解属性名: " +
                        field.getAnnotation(Bottom.class).name());
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

执行结果:
MyColor.RED.children:         [LIGHT_RED, DARK_RED]
MyColor.LIGHT_RED.children:   [DARK_RED]
MyColor.bottoms:              [DARK_RED]
MyColor.DARK_RED的注解属性名: 深红色

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值