首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【JavaSE】Enum枚举类 && 构造方法

【JavaSE】Enum枚举类 && 构造方法

原创
作者头像
lirendada
发布2026-03-25 13:59:16
发布2026-03-25 13:59:16
490
举报
文章被收录于专栏:JavaJava

Ⅰ. 定义与使用

代码语言:javascript
复制
public enum Color {
    RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, PINK, BROWN, BLACK, WHITE;
}

每个我们写的 enum 类都会默认继承于一个抽象类 Enum,如下图所示:

而这个 Enum 抽象类中有挺多方法,如下所示:

下面是使用举例:

代码语言:javascript
复制
public static void main(String[] args) {
    // 使用Color.RED直接访问枚举元素,或者直接RED都行,但不能使用new来生成枚举类对象
    Color color = Color.RED;
    System.out.println(color.name());    // 输出颜色名称
    System.out.println(color.ordinal()); // 输出颜色的序号
    System.out.println(color); // 直接输出颜色对象
    System.out.println(color.describeConstable()); // 输出颜色的描述信息
    System.out.println(Color.valueOf("BLACK"));    // 通过名称获取枚举值

    // 有个比较特殊的是values()方法,它可以返回所有枚举值数组,它不存在Enum中,而是在编译时由编译器生成的。
    // 但是如果枚举值太多,可能导致内存溢出,所以一般不用这个方法。
    System.out.println("----------------------输出所有枚举元素:");
    Color[] colors = Color.values();
    for(int i = 0; i < colors.length; ++i) {
        System.out.println(colors[i] + " " + colors[i].ordinal());
    }
    
    Color c2 = new Color(); // ❌不能实例化枚举类,只能通过枚举值访问其属性和方法。  
}

// 运行结果:
RED
0
RED
Optional[EnumDesc[Color.RED]]
BLACK
----------------------输出所有枚举元素:
RED 0
GREEN 1
BLUE 2
YELLOW 3
ORANGE 4
PURPLE 5
PINK 6
BROWN 7
BLACK 8
WHITE 9

这里要注意 values() 是由 Java 编译器为每个枚举类自动生成的静态方法,所以在 Enum 类里是找不到它的源码的,但每个具体的枚举类都有它。

还有就是枚举类内也可以有方法,并且这些方法只能通过枚举元素来调用,而不能直接通过枚举类名来调用,如下图所示:

Ⅱ. 枚举类的构造方法默认就是 private

枚举类的构造方法是隐式 private 的,是为了:

  • 保证枚举常量的唯一性
  • 避免外部创建新的实例(防止破坏 enum 的封闭性)
  • 在某些场景下,天然实现单例模式,并且是线程安全的、防反射、防反序列化

首先枚举类也是可以写构造函数,然后枚举元素可以进行构造,如下所示:

代码语言:javascript
复制
public enum Color {
    RED("red", 1), GREEN("green", 2), BLUE("blue", 3);

    private String name;
    private int value;

    // 构造函数默认就是private,不写也可以,但是不能写其它的访问权限
    private Color(String name, int value) {
        this.name = name;
        this.value = value;
    }

    public static void main(String[] args) {
        Color c = Color.RED;
        System.out.println(c.name);
        System.out.println(c.value);
    }
}

// 运行结果:
red
1

然后测试一下不同对象引用同一个枚举元素,是不是同一地址:

代码语言:javascript
复制
public static void main(String[] args) {
    Color c1 = Color.RED;
    Color c2 = Color.RED;
    System.out.println(c1 == c2); // true
}

很明显不同对象引用同一个枚举元素,都是同一个对象

然后看一下是不是能够在类内调用构造方法:

代码语言:javascript
复制
public static void main(String[] args) {
    Color c = new Color(); // ❌报错:无法实例化枚举类型
}

那么就想,能不能用反射来设置访问权限,强制调用构造方法,如下所示:

代码语言:javascript
复制
public static void main(String[] args) {
    try {
        // 先获取构造函数,再设置Accessible为true
        Class<?> cs = Class.forName("EnumDemo.Color");
        Constructor<?> ctor = cs.getDeclaredConstructor(String.class, int.class);
        ctor.setAccessible(true);

        // 调用构造函数创建对象
        Color c = (Color)ctor.newInstance("yellow", 4);
        System.out.println(c.name + " " + c.value);

    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
    } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
    } catch (InstantiationException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

然后报了如下错误:

其实这个参数错误,是因为每个枚举类都默认继承了 Enum,而 Enum 类的构造方法又有两个参数,如下所示:

这时就需要一起放在我们的枚举类的参数列表中传入才行:

代码语言:javascript
复制
Constructor<?> ctor = cs.getDeclaredConstructor(String.class, int.class, String.class, int.class);

解决上述问题之后,此时又有一个错误如下所示:

点击第二行跳转过去看看源码:

总结

  1. Enum 类同样有构造方法,但一定得是 private 修饰
  2. Enum 类的每一个枚举元素都是【单例】
  3. Enum 类型的类不能通过调用【构造方法】来创建实例
  4. Enum 类型的类不能通过【反射】来创建新的实例,因为 Enum 的实例在编译时就已经确定,且 JVM 保证了这些实例的唯一性。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Ⅰ. 定义与使用
  • Ⅱ. 枚举类的构造方法默认就是 private
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档