JAVA中的枚举类

什么是枚举类

某些情况下,一个类的对象是有限的、固定的,比如一周有7天、一年有12个月等。这种情况下,就需要使用枚举类。JAVA中借助enum关键字构建枚举类,enum关键字和class、interface关键字地位相同,所以一个JAVA源文件中最多只能定义一个public修饰的枚举类,并且Java源文件必须和该枚举类类名相同。例如:

public enum seasonEnum {
	SPRING,SUMMER,FALL,WINTER;
}

上述代码中定义了一个季节枚举类,在定义枚举类时,需要显示的列出所有枚举值,例如:SPRING,SUMMER,FALL,WINTER。枚举类的使用如下:

class enumTest{
	public void judge(seasonEnum s) {
		switch(s)
		{
			case SPRING:
				System.out.println("春天");
				break;
			case SUMMER:
				System.out.println("夏天");
				break;
			case FALL:
				System.out.println("秋天");
				break;
			case WINTER:
				System.out.println("冬天");
				break;
		}
	}
}
public enum seasonEnum {
	SPRING,SUMMER,FALL,WINTER;
	public static void main(String[] args) {
		for(seasonEnum s : seasonEnum.values()) {
			System.out.println(s);
		}
		new enumTest().judge(seasonEnum.FALL);
	}
}

上述代码中展示了两种不同的枚举类使用方法,一种借助枚举类默认的values()方法,直接返回枚举类的所有实例;另一种借助枚举类.实例(seasonEnum.FALL)来访问。同时可以看到,switch表达式中,可以使用枚举类对象。
总体来说,枚举类和普通类的区别有:

  1. 枚举类可以实现一个或多个接口,但不能显示的继承其他父类。因为JAVA中枚举类默认继承java.lang.Enum类,而并非object类
  2. 使用enum关键字定义非抽象枚举类时,默认使用final修饰,因此不能派生子类
  3. 枚举类的构造器只能使用private修饰
  4. 枚举类的实例必须在其代码块的第一行显示列出,否则该类永远无法产生实例。
  5. 枚举类的实例默认由public static final修饰

由于所有枚举类都继承了java.lang.Enum类,因此,所有枚举类都可以使用该类的方法,具体包括:

  1. int compareTo(E o):对比枚举对象的顺序
  2. String name():返回枚举实例的名称
  3. int ordinal():返回枚举对象在枚举类中的索引值(从0开始)
  4. String toString():返回枚举常量名称,与name方法类似,但toString方法更常用
  5. Enum.valueof(enumType,String name):返回指定枚举类中指定名称的枚举值

枚举类的成员变量、方法和构造器

枚举类中定义成员变量如下:

enum Gender{
	MALE,FEMALE;
	public String name;
}
public class GenderTest {
	public static void main(String[] args) {
		Gender.MALE.name = "女性";
		Gender g = Enum.valueOf(Gender.class,"FEMALE");
		g.name = "男性";
	}
}

上述代码中,分别借助 Enum.valueof方法、枚举类.实例两个方法来访问枚举类实例。随后使用枚举类实例来访问成员变量。但是这种做法是很差的,因为JAVA应该把所有的类设计成良好封装的类,所以,不应该让类的实例直接访问类的成员变量,因为别的类可能对这个乱改,因此可以改进如下:

enum Gender{
	MALE,FEMALE;
	private String name;
	public void setName(String name) {
		switch(this) {
			case MALE:
				if (name.equals("男性")) {
					this.name = name;
				}
				else
				{
					System.out.println("参数错误");
					return;
				}
				break;
			case FEMALE:
				if(name.equals("女性")) {
					this.name = name;
				}
				else
				{
					System.out.println("参数错误");
					return;
				}
				break;
		}
	}
	public String getName() {
		return this.name;
	}
}
public class GenderTest {
	public static void main(String[] args) {
		Gender.MALE.setName("男性");
		//下方代码输出,参数错误
		Gender.FEMALE.setName("男性");
		System.out.println(Gender.MALE.getName());
	}
}

上方代码保证了其他程序不能直接访问name,并且name的赋值必须合规。但是,实际上,这种处理方式依旧不够好,因为枚举类通常应该设计为不可变类,name值不应该被允许修改。
因此,枚举类的成员变量应该使用private final修饰。那么,就应该在构造器中为这些成员变量赋值,所以枚举类应该显示的定义含参构造器,进而,在列出枚举值时,就必须对应的传入参数。
综上,代码应改进为:

enum Gender{
	MALE("男性"),FEMALE("女性");
	private final String name;
	private Gender(String name) {
		this.name = name;
	}
	public String getName() {
		return this.name;
	}
}
public class GenderTest {
	public static void main(String[] args) {
		System.out.println(Gender.FEMALE.getName());
	}
}

这样成员变量就是不可变,只能访问的了。
在Gender枚举类创建了含参构造器之后,枚举类的第一行的实例可以直接调用,无需使用new关键字等。

枚举类实现接口

枚举类实现一个或多个接口和普通类基本相同,如下:

interface GenderDesc{
	void info();
}
enum Gender implements GenderDesc{
	MALE,FEMALE;
	public void info() {
		System.out.println("枚举类实现接口");
	}
}
public class GenderTest {
	public static void main(String[] args) {
		Gender.FEMALE.info();
		Gender.MALE.info();
	}
}

两行代码均输出:枚举类实现接口。可见,不同实例的行为方式是相同的,如何实现不同实例的行为方式不同呢?如下:

interface GenderDesc{
	void info();
}
enum Gender implements GenderDesc{
	MALE
	{
		public void info() {
			System.out.println("枚举类男性实例实现接口");
		}
	},
	FEMALE
	{
		public void info() {
			System.out.println("枚举类女性实例实现接口");
		}	
	};	
}
public class GenderTest {
	public static void main(String[] args) {
		Gender.FEMALE.info();
		Gender.MALE.info();
	}
}

当创建MALE、FEMALE两个枚举类实例时,后面紧跟了一对花括号,花括号中的部分其实就是一个类体部分,可以把这部分理解为匿名内部类。由此实现枚举类不同实例的行为方法不同。

包含抽象方法的枚举类

当枚举类包含抽象方法时,系统会自动为其添加abstract关键字,因此不可以人工再添加。由于枚举类需要显示的创建实例,而并非作为父类,因此定义每个枚举实例时,必须为抽象方法提供实现,否则报错,如下:

public enum Operation {
	PLUS{
		public double eval(double x, double y) 
		{
			return x + y;
		}
	},
	MINUS{
		public double eval(double x,double y) 
		{
			return x - y;
		}
	},
	TIMES{
		public double eval(double x,double y) 
		{
			return x*y;
		}
	},
	DIVIDE{
		public double eval(double x,double y) 
		{
			return x/y;
		}
	};
	public abstract double eval (double x, double y);
	public static void main(String[] args) {
		System.out.println(Operation.PLUS.eval(3.1,5.5));
		System.out.println(Operation.MINUS.eval(3.1,5.5));
		System.out.println(Operation.TIMES.eval(3.1,5.5));
		System.out.println(Operation.DIVIDE.eval(3.1,5.5));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值