2021-11-13 枚举、Enum中的常用类、Enum中添加新方法、switch语句中的Enum、Enum静态导入、枚举实现单例设计模式

本文详细介绍了Java中枚举类型的多种实现方式,包括静态常量、单例模式以及枚举类,并展示了如何在switch语句中使用枚举。枚举的优势在于其安全性与明确的语义,避免了常量的误修改风险和语义模糊问题。此外,枚举还可以用于实现单例设计模式。最后,文章提到了阿里巴巴开发手册中关于枚举的规范,强调了枚举在代码规范和可读性上的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

枚举

1、引入

在某些情况下,一个类的对象的实例有限且固定的,如季节类,它只有春夏秋冬4个对象,再比如星期,在这种场景下我们可以使用枚举。当然我们也可以有自己的方法来实现,
法一:

public class SeasonConstant {
	public static final int SPRING = 1;
	public static final int SUMMER = 2;
	public static final int AUTUMN = 3;
	public static final int WINTER = 4;
}

这种方式,我们可以简单的表示春夏秋冬四个季节,但是扩展性很差,我们想给春夏秋冬附加更多信息的时候就无能为力的,静态常量能保证内存独此一份,更够很好的表示春夏秋冬四个季节,同时不允许别人修改。

法二:利用类似单例模式的方案
既然使用基础数据类型无法表示丰富的内容,我们不妨把基础类型改为引用数据类型。

public class Season {
	private int value;
	private String name;
	// 定义四个静态常量让每个季节在内存中独此一份
	public static final Season SPRING = new Season(1,"春天");
	public static final Season SUMMER = new Season(2,"夏天");
	public static final Season AUTUMN = new Season(3,"秋天");
	public static final Season WINTER = new Season(4,"冬天");
	private Season(){
	}
	private Season(int value, String name) {
		this.value = value;
		this.name = name;
	}
	public int getValue() {
		return value;
	}
	public void setValue(int value) {
		this.value = value;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

通过以上方法我们可以实现内存中只有这四个对象,这是合情理的,因为一年四季只能是各一个对象才对,想要用的时候直接用类名去调用就行,但是这样写太复杂了!

法三:将重复的去掉

public class Season {
	// 定义四个静态常量让每个季节在内存中独此一份
	SPRING,SUMMER,AUTUMN,WINTER;
}

这样写太不合逻辑!class不支持!

法四:改进

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

注:原理就是看懂字节码中的name和ordinal属性就行(在out文件夹中找到类–>open in—>terminal—>javap -v .\方法名.class)

2、Enum中的常用类

在这里插入图片描述

注:values()方法在编译的jvm会自动提供。

本例中的values()方法和valueOf()方法的字节码片段:
在这里插入图片描述
在这里插入图片描述

3、Enum中添加新方法

Enum 可以看做是一个常规类(除了不能继承自一个enum),enum中可以添加方法和 main 方法。

public enum SeasonEnum {
	SPRING("春天","春暖花开的季节"),
	SUMMER("夏天","热的要命,但是小姐姐都穿短裤"),
	AUTUMN("秋天","果实成熟的季节"),
	WINTER("冬天","冷啊,可以吃火锅");
	private String name;
	private String detail;
		SeasonEnum() {
	}
	SeasonEnum(String name, String detail) {
		this.name = name;
		this.detail = detail;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDetail() {
		return detail;
	}
	public void setDetail(String detail) {
		this.detail = detail;
	}
}

注:要定义有参构造时,一定定义无参构造,

4、switch语句中的Enum

注意用法:

public static void main(String[] args) {
	SeasonEnum season = SeasonEnum.SPRING;
	switch (season){
		case SPRING:
			System.out.println("春天来了,又到了万物交配的季节!");
		case SUMMER:
			System.out.println("夏天来了,又可以穿大裤衩了!");
		case AUTUMN:
			System.out.println("秋天来了,又到了收获的季节!");
		case WINTER:
			System.out.println("冬天来了,又到了吃火锅的季节了!");
		default:
			System.out.println("也没有别的季节了。");
	}
}

注:常规情况下必须使用 enum 类型来修饰 enum 实例,但在 case 语句中不必如此,即 case SPRING: 不需要写成 case SeasonEnum.SPRING:

5、静态导入

static import 可以将 enum 实例的标识符带入当前类,无需再用enum类型来修饰 enum 实例。

import static com.ydlclass.SeasonEnum.*;
	public class Test {
	public static void main(String[] args) {
	System.out.println(SPRING.name());
	System.out.println(SUMMER.name());
}

6、枚举实现单例设计模式

目前我们的单例设计模式已经实现了三种了:
《Effective Java》
这种方法在功能上与公有域方法相近,但是它更加简洁,无偿提供了序列化机制,绝对防止多次实例化,即使是在面对复杂序列化或者反射攻击的时候。虽然这种方法还没有广泛采用,但是单元素的枚举类型已经成为实现 Singleton的最佳方法。—《Effective Java 中文版第二版》
懒汉式:

package com.ydlclass;
public class Singleton {
	//实现一个私有的构造器
	private Singleton(){}
	//得到一个对象对外公开
	public static Singleton getInstant(){
		return SingletonHolder.INSTANT.instant;
	}
	//new一个Singleton的对象
	private enum SingletonHolder{
		INSTANT;
		private final Singleton instant;
		SingletonHolder(){
		instant = new Singleton();
		}
	}
	public static void main(String[] args) {
		System.out.println(Singleton.getInstant() == Singleton.getInstant());
	}
}

7、枚举的优势

阿里《Java开发手册》对枚举的相关规定如下,我们在使用时需要稍微注意一下。
【强制】 所有的枚举类型字段必须要有注释,说明每个数据项的用途。
【参考】 枚举类名带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。

  • 第一, int 类型本身并不具备安全性,假如某个程序员在定义 int 时少些了一个 final
    关键字,那么就会存在被其他人修改的风险,而反观枚举类,它“天然”就是一个常量类,不存在被修改的风险(原因详见下半部分);
  • 第二,使用 int 类型的语义不够明确,比如我们在控制台打印时如果只输出 1…2…3
    这样的数字,我们肯定不知道它代表的是什么含义。那有人就说了,那就使用常量字符呗,这总不会还不知道语义吧?

实现示例代码如下:

public static final String COLOR_RED = "RED";
public static final String COLOR_BLUE = "BLUE";
public static final String COLOR_GREEN = "GREEN";

但是这样同样存在一个问题,有些初级程序员会不按套路出牌,他们可能会直接使用字符串的值进行比较,而不是直接使用枚举的字段,实现示例代码如下:

public class EnumTest {
	public static final String COLOR_RED = "RED";
	public static final String COLOR_BLUE = "BLUE";
	public static final String COLOR_GREEN = "GREEN";
	public static void main(String[] args) {
		String color = "BLUE";
		if ("BLUE".equals(color)) {
			System.out.println("蓝色");
		}
	}
}

这样当我们修改了枚举中的值,那程序就凉凉了。

枚举比较推荐使用 “==”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值