SE高阶(18):枚举类的用法和应用场景

本文详细介绍了枚举类的基本概念,包括其构造器的私有化、枚举值的声明和特性。枚举类的实例数量在编译时即固定,不能动态创建。此外,枚举类的用法和多种应用场景也进行了探讨。

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

 枚举类简要介绍 

     
       枚举是Java1.5引入的新特性,通过关键字enum来定义枚举类,enum关键字和class、interface、@interface(注解)的地位是相同的。枚举类是一种特殊类,它和普通类一样可以使用构造器、定义成员变量和方法,也能实现一个或多个接口。但枚举类不能继承其他类,因为枚举类默认继承java.lang.Enum类(注:Enum是抽象类),Java是单继承,所以不允许。

 枚举类的特点 

  • 枚举类的构造器默认被private修饰,如果显式指定,也只能用private来修饰,不然会报错。
  • 枚举类的实例必须在第一行显式列出,不然无法生成枚举实例,枚举实例就是枚举值。
  • 枚举值默认被public final static修饰。枚举类默认被final修饰,无法被继承。
  • 枚举值可以看作静态常量对象,除了拥有常量的特性外,还和对象一样可以调用方法、成员变量。
  • 和普通类比起来,枚举类对象数量在第一行就被固定下来了,不能随意创建。
public enum Color {
	RED, GREEN, BLUE;	
}
//编译上面枚举类后,会生成对应的字节码文件:Color.class
       通过上面代码,可以看出编译后的枚举类和普通类大致差不多,只是用法稍有不同。我们再来看一下,列出枚举值时无需指定类型,平时定义常量时是要指定类型的,在上面关于枚举类的特点中,说过枚举值就是枚举类对象,所以列出枚举值就是在创建对象,这会使用到构造器,这里的构造器是默认的,这时候看一下父类代码:
 //父类Enum的构造器 
 protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
       每创建一个枚举值就会调用上述父类构造器,生成对应的enum类型静态常量,并且按照顺序设置值,初始值为0。总之,使用枚举类时,只需将枚举值看作枚举类的对象来用就行。


 枚举类的用法 

 booleanequals(Object other)
          当指定对象等于此枚举常量时,返回 true。
protected  voidfinalize()
          枚举类不能有 finalize 方法。
 Class<E>getDeclaringClass()
          返回与此枚举常量的枚举类型相对应的 Class 对象。
 inthashCode()
          返回枚举常量的哈希码。
 Stringname()
          返回此枚举常量的名称,在其枚举声明中对其进行声明。
 intordinal()
          返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
 StringtoString()
          返回枚举常量的名称,它包含在声明中。
static
<T extends Enum<T>> 
T
valueOf(Class<T> enumType,String name)
          返回带指定名称的指定枚举类型的枚举常量。


查看枚举值的序数
		System.out.println(Color.RED.ordinal());
		System.out.println(Color.GREEN.ordinal());
		System.out.println(Color.BLUE.ordinal());
		//输出序数
		0
		1
		2
        这里的序数就是定义枚举值时自动为其生成的,理论上来说可以看作是它们的初始值,但提供的数据较少,所以要为枚举值附加更多属性时,可以创建成员变量,使用构造器来赋值。其他方法的话都比较简单,在此省略示例代码。


枚举类中定义变量和方法
public enum Color {
	RED, GREEN, BLUE; //列出枚举值, 枚举类实例
	//定义实例变量和静态变量
	private int a = 10;
	private static int b = 100;
	//定义方法
	public int getA() {
		return this.a;
	}
	public static void main(String[] args) {
		Color.RED.a = 20;
		Color.RED.b = 101;
		Color.GREEN.a = 30;
		Color.GREEN.b = 102;
		System.out.println("RED.a = " + Color.RED.getA());
		System.out.println("GREEN.a = " + Color.GREEN.getA());
		//RED.a = 20
		//GREEN.a = 30
	}
}
         上面实例中,使用枚举值可以调用成员变量、实例方法,静态属性也是共享的,和普通类对象用法差不多。如果只是这样赋值的话,会显得麻烦且逻辑不清晰,所以采用用构造器来给给对象赋值的用法来给枚举值赋值,实例如下:
	RED(15), GREEN(30), BLUE(45); //为枚举值的实例变量赋值
	//定义实例变量
	private int a = 10;
	//枚举类的构造器 
	private Color(int a) {
		this.a = a;
	}
	//测试
	public static void main(String[] args) {
		System.out.println(Color.RED.a);
		System.out.println(Color.GREEN.a);
		System.out.println(Color.BLUE.a);
	}
       上面只是定义了3个枚举值,每次获取值时就显得很麻烦了,而且重复代码太多,这时就可以使用values()方法返回枚举类所有实例,转成枚举数组。但在Enum源码中并没有该方法,这个问题我也不清楚.....,改进后如下:
//使用values()来循环获取属性值。但获取属性值最好是用getXxx()来完成
	public static void main(String[] args) {
		for(Color c : Color.values()) {
			System.out.println(c.a);
		}
	}


 枚举类应用场景 


1.最常用到的当属常量,例如定义各类状态时,使用枚举类可以把相关联的常量放在一个枚举类中,并能根据需求来增加属性和方法。
public enum Sex {
	MAN("男") , MALE("女");
	private String sex;
	private Sex(String sex) {
		this.sex = sex;
	}
	//重写toString(),返回枚举值的sex属性
	@Override 
	public String toString() {
		return this.sex;
	}
	
	public static void main(String[] args) {
		System.out.println(Sex.MAN.toString());
		System.out.println(Sex.MALE.toString());
		//输出结果
		男
		女
		
	}
相较于常量而言,枚举类可以另加灵活化,还能对常量进行统一管理。


2.可以在switch语句使用枚举类,switch可以自动检查枚举值是否属于传入的枚举类
	public static void main(String[] args) {
		//得到枚举数组
		SeasonEnum[] se =  SeasonEnum.values();
		//随机获得其中一个枚举
		SeasonEnum rand = Test.getRandomEnum(se);
		switch(rand) {
			case SPRING:
				System.out.println(rand + ", 是" + rand.getSeason());
			break;
			case SUMMER:
				System.out.println(rand + ", 是" + rand.getSeason());
				break;
			case AUTUMN:
				System.out.println(rand + ", 是" + rand.getSeason());
				break;
			case WINTER:
				System.out.println(rand + ", 是" + rand.getSeason());
				break;
		}
					
	}
	/** 根据指定的枚举数组来随机获得其中一个枚举 */
	public static <T extends Enum> T getRandomEnum(T[] enumArr) {
		int index = (int)(Math.random() * enumArr.length); //生成的下标在枚举数组长度范围之内
		T rs = enumArr[index];
		return rs;
	}


3.枚举类可以在接口中定义,也可以定义在类里面,访问权限的使用和内部类一样,等于使用内部类来维护一些常量的使用。
//能定义在接口中
interface testEnum{
	enum State{
		ON, OFF;
	}
}
//定义成内部枚举类
public class Test {
	enum State{
		ON, OFF;
	}
}


4.除了以上这些,枚举还能应用于集合:EnumSet和EnumMap,Set的底层是采用Map存储key值来实现的,所以EnumSet的值和EnumMap的key一样是需要枚举类型,但Map的value类型就随意了。  由于枚举集合基本用不了,所以没有给出例子,如果有需要,可以自行查询相关资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值