枚举的使用和本质

本文深入解析Java枚举(enum)的概念及应用,介绍如何定义枚举并利用其特性增强代码的可读性和可维护性。文章涵盖了枚举的基本语法、内置方法、自定义属性和方法等内容,并探讨了枚举的本质。

枚举enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中。

一般用于定义同一类常量,如形容颜色的字符串常量,包含"RED"、"GREEN"、"BLUE"等。这些常量如果散落在常量类中(甚至零散的定义在各个要使用到这些常量的类中)不利于维护。

枚举的常见使用

语法

定义一个枚举使用关键字 emun 。如

public enum ColorEnum {
    /**红色*/
    RED,
    /**绿色*/
    GREEN,
    /**蓝色*/
    BLUE
}
public enum ColorEnum {
    /**红色*/
    RED("255 250 250"),
    /**绿色*/
    GREEN("248 248 255"),
    /**蓝色*/
    BLUE("220 220 220");
​
    /**RGB色号*/
    private String rgb;
​
    ColorEnum(String rgb) {
        this.rgb = rgb;
    }
​
    public String getRgb() {
        return rgb;
    }
}

常用方法

  • String name()

    返回此枚举常量的名称

  • int ordinal()

    返回枚举常量的序数(它在枚举声明中的位置,其中定义的一个枚举序数为零)

  • int compareTo(E o)

    比较此枚举与指定对象的顺序

    此处的顺序是指在序数的相差位数,同一枚举时返回0,其他情况返回相减得到的值

  • Class<E>getDeclaringClass()

    返回与此枚举常量的枚举类型相对应的 Class 对象。

  • String toString()

    返回枚举常量的名称,它包含在声明中。

  • static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)

    返回带指定名称的指定枚举类型的枚举常量。

  • static <T extends Enum<T>> T[] values()

    返回枚举类中所有的枚举

使用上一节定义的枚举(第二种),完成对上面方法的测试。

public class ColorEnumTest {
​
    public static void main(String[] args) {
        System.out.println("name():" + ColorEnum.BLUE.name());
        // name():BLUE
​
        System.out.println("compareTo():" + ColorEnum.BLUE.compareTo(ColorEnum.RED));
        // compareTo():2
​
        System.out.println("ordinal():" + ColorEnum.RED.ordinal());
        // ordinal():0
​
        System.out.println("getDeclaringClass():" + ColorEnum.GREEN.getDeclaringClass());
        // getDeclaringClass():class com.xxx.ColorEnum
​
        System.out.println("toString():" + ColorEnum.RED.toString());
        // toString():RED
​
        System.out.println("valueOf:" + ColorEnum.valueOf("RED"));
        // valueOf:RED
    }
}

给 enum 自定义属性和方法

在第二种枚举类的定义中,定义了一个 String 类型的 rgb 属性,在开发过程中同样可以为枚举类定义更多类似的属性。如再增加一hex属性来描述颜色的16色。

public enum ColorEnum {
    /**红色*/
    RED("255 250 250", "#FFFAFA"),
    /**绿色*/
    GREEN("248 248 255", "#F8F8FF"),
    /**蓝色*/
    BLUE("220 220 220", "#DCDCDC");
​
    /**RGB色号*/
    private String rgb;
​
    /**十六进制色号*/
    private String hex;
​
    ColorEnum(String rgb, String hex) {
        this.rgb = rgb;
        this.hex = hex;
    }
​
    public String getRgb() {
        return rgb;
    }
​
    public String getHex() {
        return hex;
    }
}

在枚举常量末尾使用 ; 分割,需要定义 ColorEnum构造器 赋值,定义 get方法 获取具体的值。

枚举的本质

使用 javap 反编译ColorEnum。得到如下结果

==此处应有图片==

PS D:\code\backend\LK02.TFE_TFE9\target\classes> javap ColorEnum.class
Compiled from "ColorEnum.java"
public final class ColorEnum extends java.lang.Enum<ColorEnum> {
  public static final ColorEnum RED;
  public static final ColorEnum GREEN;
  public static final ColorEnum BLUE;
  public static ColorEnum[] values();
  public static ColorEnum valueOf(java.lang.String);
  public java.lang.String getRgb();
  static {};
}

可以看到,枚举类通过编译,得到一个类,继承了java.lang.Enum<T>,而对于每一个枚举常量,实际上是public static final修饰的枚举类的静态实例对象。

同时注意,编译器会为我们添加两个新的static方法:values() 和 valueOf(java.lang.String),其实分别作用是返回枚举类中定义的所有的枚举常量,以及根据枚举名来获取枚举常量(注意,这里就是定义枚举常量的枚举名)。

所以对于枚举常量可以当做一组类使用,枚举常量可以当做普通的类使用

从本质看常用方法

了解了枚举的本质后,对于枚举常量的调用,name()方法、ordinal()方法等就比较好理解的了,可以看做 java.lang.Enum<T> 中定义name属性,name()等方法,在编译时为为这些属性赋值。进入到 java.lang.Enum<T> 类中,也可以看到确实是这样的

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
​
    private final String name;
​
    public final String name() {
        return name;
    }
​
    private final int ordinal;
​
    public final int ordinal() {
        return ordinal;
    }
​
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
​
    public String toString() {
        return name;
    }
​
    public final boolean equals(Object other) {
        return this==other;
    }
​
    public final int hashCode() {
        return super.hashCode();
    }
​
    protected final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
​
    public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }
​
    @SuppressWarnings("unchecked")
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }
​
    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }
​
    protected final void finalize() { }
​
    private void readObject(ObjectInputStream in) throws IOException,
        ClassNotFoundException {
        throw new InvalidObjectException("can't deserialize enum");
    }
​
    private void readObjectNoData() throws ObjectStreamException {
        throw new InvalidObjectException("can't deserialize enum");
    }
}


枚举的骚操作

为什么枚举构造器不能访问枚举的静态域

使用抽象函数为枚举统一方法

EnumSet,EnumMap 的应用

<think>好的,我现在需要帮助用户了解如何在编程中定义使用枚举类型,并提供示例语法。首先,我得回忆一下不同编程语言中枚举的定义方式,因为用户可能对多种语言感兴趣,或者需要通用的概念。 用户之前提到了JavaC的例子,引用中提到了Java使用点语法访问枚举常量,而C可能需要其他方法。因此,我应该涵盖几种常见语言,比如Java、C、Python,可能还有C++,这样用户可以得到全面的信息。 首先,定义枚举类型的基本概念。枚举用于定义一组命名的常量,提高代码可读性类型安全。然后,分语言说明语法使用方法。 对于Java枚举是一个类,可以有自己的方法构造函数。示例代码可能包括定义一个颜色枚举,然后访问它的常量使用方法,比如name()。同时,引用中的例子提到MailInfoMsgEnum.friend,这可以作为另一个例子,但用户需要基础示例,所以用颜色更合适。 C语言的枚举类型大小可能由编译器决定,通常一个枚举变量占4字节。但用户之前的问题提到C中可能需要1字节的枚举,这里可能需要说明C的限制,比如使用#define或char类型,但会失去类型安全。示例中应该展示enum关键字的使用,比如定义颜色枚举,但指出其存储大小的问题,并提到替代方法。 Python从3.4版本引入Enum模块,所以需要展示如何使用它。示例包括定义枚举类,并通过成员名或值访问。同时,可以提到Python枚举的特点,比如不可实例化,支持迭代等。 C++的枚举分为有作用域enum class无作用域enum,需要区分两者的不同,比如作用域隐式转换。示例展示两种定义方式,并说明访问时的区别。 接下来,应用场景部分需要说明何时使用枚举,比如状态码、选项、有限集合等,强调可读性维护性。 注意事项中要提到不同语言的差异,比如类型安全、存储大小,以及如何选择适合的方法。例如,C中类型不安全的问题,Java枚举功能更强大等。 生成的相关问题需要围绕枚举的深入使用,比如比较不同语言的实现、最佳实践、底层实现、与常量的对比等。这些问题可以帮助用户进一步探索。 需要确保所有代码示例正确,并且符合各语言的语法规范。例如,Java枚举用分号分隔常量,C的枚举用逗号,Python需要导入Enum类等。同时,按照用户要求,行内公式用$...$,但这个问题可能不涉及数学公式,所以可能不需要使用,但需要检查是否有遗漏。 最后,检查引用是否正确应用,用户提供的引用[1][2]分别关于JavaC的枚举,需要在回答中适当提及,比如在Java部分末尾添加引用[^1],在C部分提到替代方法时引用[^2]。 总结步骤:分语言讲解定义语法、示例代码、应用场景、注意事项,最后生成相关问题。确保结构清晰,示例正确,引用适当。</think>### 枚举类型的定义与使用 枚举(Enum)是编程中用于定义一组**命名常量**的数据类型,可提高代码可读性类型安全性。以下是不同语言中枚举的定义语法、使用示例及注意事项。 --- ### 1. 基础语法示例 #### Java ```java // 定义枚举类型 enum Color { RED, GREEN, BLUE; // 枚举常量 } // 使用示例 Color myColor = Color.RED; System.out.println(myColor.name()); // 输出 "RED" [^1] ``` #### C ```c // 定义枚举类型 enum Color { RED, GREEN, BLUE }; // 使用示例 enum Color c = RED; printf("%d", c); // 输出 0(默认从0开始编号) ``` #### Python(3.4+) ```python from enum import Enum # 定义枚举类型 class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 # 使用示例 print(Color.RED.value) # 输出 1 ``` #### C++ ```cpp // 定义强类型枚举(C++11+) enum class Color { RED, GREEN, BLUE }; // 使用示例 Color c = Color::RED; ``` --- ### 2. 核心功能 - **命名常量**:用语义化名称代替数字(如`RED`代替`0`)。 - **类型安全**(部分语言):避免误用无效值(如Java/C++枚举无法直接赋值整数)。 - **遍历枚举值**:可迭代所有枚举常量(如Python中`list(Color)`)。 --- ### 3. 应用场景 1. **状态码**:定义HTTP状态码(如`HTTPStatus.OK`)。 2. **有限选项**:如方向(`UP, DOWN, LEFT, RIGHT`)。 3. **配置参数**:如日志级别(`DEBUG, INFO, ERROR`)。 --- ### 4. 注意事项 - **语言差异**: - C中枚举本质是整数,无类型安全[^2]。 - Java/Python/C++支持附加方法或属性。 - **存储优化**:若需节省内存(如嵌入式系统),C中可用`#define`替代(但失去类型检查)[^2]。 --- ### 代码示例(Java附加方法) ```java enum HttpStatus { OK(200), NOT_FOUND(404); private final int code; HttpStatus(int code) { this.code = code; } public int getCode() { return code; } } // 使用 HttpStatus status = HttpStatus.OK; System.out.println(status.getCode()); // 输出 200 [^1] ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值