Java之枚举(enum)--使用/教程/实例

原文网址:Java之枚举(enum)--使用/教程/实例_IT利刃出鞘的博客-CSDN博客

简介

说明

本文用示例介绍Java中的枚举(enum)的用法。

使用场景

定义常量、状态机等。

枚举与常量类

常量类

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

public interface IConstants{
	public static final int RED = 1;
	public static final int BLUE = 2;
	public static final int GREEN = 3;
}

枚举与常量类的对比

枚举类常量类
单例

完全单例、线程安全。

枚举类编译后类为:public final class T extends Enum,不允许继承可防止被子类修改。

不单例

常量类可被继承修改、增加字段等,容易导致父类的不兼容。

性能

性能高。

常量值地址唯一,可以用==直接对比

性能低

使用常量类时,往往得通过equals去判断两者是否相等。

引用类

不需重新编译引用类。

枚举类编译时,没有把常量值编译到代码里,即使常量的值发生变化,也不会影响引用常量的类。

需要重新编译引用类。

常量类编译时,是直接把常量的值编译到类的二进制代码里,常量的值在升级中变化后,需要重新编译引用常量的类,因为里面存的是旧值。

越界

不会越界。

编译期间限定类型,不允许发生越界的情况。

可能越界。

switch语句支持枚举型,当switch使用int、String类型时,由于值的不稳定性往往会有越界的现象,对于这个的处理往往只能通过if条件筛选以及default模块来处理。

枚举与普通类

差别不大。枚举也可以定义变量与方法:

package com.example.a;

enum MyEnum{
    FIRST("第一个"),
    SECOND("第二个"),
    ;

    private final String description;
    
    MyEnum(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    private String lastName;

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

public class Demo {
    public static void main(String[] args) {
        MyEnum.FIRST.setLastName("Tony");
        System.out.println(MyEnum.FIRST.getLastName());
        System.out.println(MyEnum.FIRST.getDescription());
    }
}

执行结果

Tony
第一个

枚举与数据库

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

在下边的例子中,如果某个类中的字段为:private PersonType type; 则其对应的数据库中的值为:"STUDENT"、"TEACHER"。

package com.example.a;

public enum PersonType{
    STUDENT("学生"),
    TEACHER("教师"),
    ;

    private final String description;

    PersonType(String description) {
        this.description = description;
    }

    public String getDesc() {
        return description;
    }
}

基础示例

一个参数

实例 

package com.example.a;

enum PayTypeEnum{
    ALIPAY("支付宝"),
    WECHAT("微信"),
    UNION_PAY("银联"),
    ;

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

    //必须提供为私有的,防止外部new对象
    PayTypeEnum(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

public class Demo {
    public static void main(String[] args){
        for (PayTypeEnum value : PayTypeEnum.values()) {
            System.out.println("name:" + value.name() + "," + "description:" + value.getDescription());
//            下边这样写结果是一样的
//            System.out.println("name:" + value.toString() + "," + "description:" + value.getDescription());
        }
    }
}

运行结果

name:ALIPAY,desc:支付宝
name:WECHAT,desc:微信
name:UNIONPAY,desc:银联

多个参数

实例 

package com.example.a;

interface IEnum{
    String getCode();
    String getDescription();
}

enum PayTypeEnum implements IEnum{
    ALIPAY("ALIPAY", "支付宝"),
    WECHAT("WECHAT", "微信"),
    UNION_PAY("UNION_PAY", "银联"),
    ;

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

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

    //必须提供,而且是私有的,防止外部new对象
    PayTypeEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }

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

    @Override
    public String getCode() {
        return this.code;
    }

    @Override
    public String getDescription() {
        return this.description;
    }
}

public class Demo {
    public static void main(String[] args){
        System.out.println(PayTypeEnum.getDescriptionByCode(PayTypeEnum.ALIPAY.getCode()));
        System.out.println(PayTypeEnum.getDescriptionByCode(PayTypeEnum.WECHAT.getCode()));
    }
}

运行结果

支付宝
微信

异常处理应用

异常码枚举

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

}

测试类

package enums.expection;

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

高级操作

接口中定义注解

package org.example.a;

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

枚举上使用注解

见:Java--Annotation(注解)--使用/应用/实例_IT利刃出鞘的博客-CSDN博客

实现原理

枚举类

package org.example.a;

public enum Season {
    SPRING, SUMMER, AUTUMN, WINTER;
}

反编译代码

public final class Season extends Enum
{
    private Season(String s, int i)
    {
        super(s, i);
    }
    public static Season[] values()
    {
        Season at[];
        int i;
        Season at1[];
        System.arraycopy(at = ENUM$VALUES, 0, at1 = new Season[i = at.length], 0, i);
        return at1;
    }

    public static Season valueOf(String s)
    {
        return (Season)Enum.valueOf(demo/Season, s);
    }

    public static final Season SPRING;
    public static final Season SUMMER;
    public static final Season AUTUMN;
    public static final Season WINTER;
    private static final Season ENUM$VALUES[];
    static
    {
        SPRING = new Season("SPRING", 0);
        SUMMER = new Season("SUMMER", 1);
        AUTUMN = new Season("AUTUMN", 2);
        WINTER = new Season("WINTER", 3);
        ENUM$VALUES = (new Season[] {
            SPRING, SUMMER, AUTUMN, WINTER
        });
    }
}

分析

通过反编译后代码可见,该类继承了Enum类,同时final关键字表明这个类不能被继承。

字段都是static类型的,static类型的属性会在类被加载之后被初始化。当一个Java类第一次被真正使用到的时候静态资源被初始化、Java类的加载和初始化过程都是线程安全的。所以,创建一个enum类型是线程安全的。

  • 21
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Java枚举类型enum)是一种特殊的类,它表示一组常量,可以用于定义一组相关的常量,例如一周的天数、月份、颜色等等。 使用枚举类型可以提高代码的可读性和可维护性,因为它可以将常量集中管理,避免了在代码中出现大量的魔法数字。 下面是Java枚举类型使用方法: 1. 定义枚举类型: ``` enum Weekday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY } ``` 2. 使用枚举类型: ``` Weekday day = Weekday.MONDAY; System.out.println(day); // 输出 MONDAY ``` 枚举类型可以作为方法参数或返回值,例如: ``` public enum Gender { MALE, FEMALE; public static Gender fromString(String s) { if (s.equalsIgnoreCase("male")) { return MALE; } else if (s.equalsIgnoreCase("female")) { return FEMALE; } else { throw new IllegalArgumentException("Invalid gender: " + s); } } } public class Person { private String name; private Gender gender; public Person(String name, Gender gender) { this.name = name; this.gender = gender; } public String getName() { return name; } public Gender getGender() { return gender; } } // 使用枚举类型作为方法参数和返回值 public static void main(String[] args) { Person p1 = new Person("Tom", Gender.MALE); Person p2 = new Person("Mary", Gender.FEMALE); System.out.println(p1.getName() + " is " + p1.getGender()); // 输出 Tom is MALE System.out.println(p2.getName() + " is " + p2.getGender()); // 输出 Mary is FEMALE Gender gender = Gender.fromString("male"); System.out.println("Gender from string: " + gender); // 输出 Gender from string: MALE } ``` 枚举类型还可以定义构造方法、实例方法、静态方法和成员变量,例如: ``` enum Color { RED("FF0000"), GREEN("00FF00"), BLUE("0000FF"); private String code; private Color(String code) { this.code = code; } public String getCode() { return code; } public static Color fromCode(String code) { for (Color c : values()) { if (c.code.equalsIgnoreCase(code)) { return c; } } throw new IllegalArgumentException("Invalid color code: " + code); } } public static void main(String[] args) { Color c1 = Color.RED; Color c2 = Color.fromCode("00FF00"); System.out.println(c1.getCode()); // 输出 FF0000 System.out.println(c2.name()); // 输出 GREEN } ``` 总之,Java枚举类型是一种强大的语言特性,它可以用于定义一组相关的常量,并提供了丰富的方法来操作这些常量。在实际开发中,我们应该尽可能地使用枚举类型来管理常量,以提高代码的可读性和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT利刃出鞘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值