Java中枚举类的深入理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tianjindong0804/article/details/86421108

概述

在此之前由于个人在学习和开发中对枚举类的应用较少,所以对枚举类的知识点并没进行深入的了解,但最近写代码中突然想到了枚举类,抱着完善自身的知识的目的,就较为深入的了解了Java中的枚举类。

我在学习任何东西之前都会大致弄清楚这个东西存在的目的是什么,这样才能更加深入的理解一些东西。同样的,在学习枚举类之前,我们也需要摸清楚Java5才出来的枚举类到底有什么作用。

 

为什么会出现枚举类

这里我们给出一种场景,给出一个Employee类,该类需要定义一个字段保存这个员工休息日(周一到周日的一天),那我们如何表示呢?


有人可能就说了直接定义成int型不就行了,1表示星期一.....。代码也就是这样的:

public class Employee {
	private String name;
	private int playday;
	
	public Employee(String name, int playday) {
		super();
		this.name = name;
		this.playday = playday;
	}
}

但是问题来了,使用这个类的用户怎么知道传进去的数字代表的是什么,更危险的是用户可以传入一个负数,这显然就不符合要求了。可能有些人就会说了,在方法上面写一个注释不就行了,但是这么做明显是把命运交给了别人,万一别人就是不按规定来呢?


我们来对程序做第一版改进:

public class Employee {
	public static final int Mon=1;
	public static final int Tues=2;
	public static final int Wed=3;
	public static final int Thur=4;
	public static final int Fri=5;
	public static final int Sat=6;
	public static final int Sun=7;
	
	private String name;
	private int playday;
	
	public Employee(String name, int playday) {
		super();
		this.name = name;
		this.playday = playday;
	}
}

这样我们每次在创建Employee对象过程中传入int类型值时就不需要手动指定一个常量值了,只需要使用Employee中定义的静态常量即可。就像这样:

Employee employee = new Employee("zhangsan", Employee.Fri);

但是这么做并没有完全解决上面所说的问题,用户还是可以手动指定指定一个整数类型的值。看来我们还需要对程序进行改进:


第二版改进:我们需要重新定义一个类来表示星期了!

public class WeekDay {
	public static final WeekDay Mon=new WeekDay(1, "Mon");
	public static final WeekDay Tues=new WeekDay(2, "Tues");
	public static final WeekDay Wed=new WeekDay(3, "Wed");
	public static final WeekDay Thur=new WeekDay(4, "Thur");
	public static final WeekDay Fri=new WeekDay(5, "Fri");
	public static final WeekDay Sat=new WeekDay(6, "Sat");
	public static final WeekDay Sun=new WeekDay(7, "Sun");
	
	private int day;
	private String info;
	
        //构造器被私有化
	private WeekDay(int day, String info) {
		super();
		this.day = day;
		this.info = info;
	}
}

此时Employee类需要进行相应的改进

public class Employee {
	private String name;
	private WeekDay playday;
	
	public Employee(String name, WeekDay playday) {
		super();
		this.name = name;
		this.playday = playday;
	}
}

经过两次改进程序得到了完善,由于WeekDay类的构造器被私有化(别和我杠可以通过反射等手段获得新的WeekDay对象),所以用户在创建Employee对象时只能使用WeekDay中的静态常量了,所以最初的那些问题也就解决了。

但是!!!!!!!!

你没觉得这么写太麻烦了吗?为了Employee类中的一个属性,需要重新建一个表示常量的类,并且代码还比较多,此时Java5出来的特性——枚举类就可以简单的解决这个问题了。

 

引入枚举类

Java 5新增了一个enum关键字(表面上看它与class interface地位相同),用于定义枚举类。

我们通过枚举类对第二次改版的代码进行改造:

定义枚举类:

public enum WeekDayEnum {
	Mon,Tues,Wed,Thu,Fri,Sat,Sun;
}

改造Employee类:

public class Employee {
	private String name;
	private WeekDayEnum playday;
	
	public Employee(String name, WeekDayEnum playday) {
		super();
		this.name = name;
		this.playday = playday;
	}
}

创建Employee对象:

Employee lisi = new Employee("lisi", WeekDayEnum.Mon);

这么写代码是不是发现简单了很多,文化人要说“优雅”这个词,哈哈。

那我们就来说说Java中的枚举类的语法规则:

1. 枚举类的所有的常量(或者说是枚举类的实例)必须在第一行中列出来,常量与常量之间用逗号隔开,列出来的常量系统会自动加上 public static final修饰符,不需要程序员手动添加。

2. 枚举类可以实现一个或多个接口。

3. 枚举类的构造器只能用只能使用private修饰,不然会报错,如果省略修饰符那么系统会默认加上private。

 

你以为说完枚举类的语法,枚举类就学完了??

哪有这么简单。。。。

深入理解枚举类

我们将WeekDayEnum类通过XJad反编译工具进行反编译,反编译的结果如下:

public final class WeekDayEnum extends Enum
{

	public static final WeekDayEnum Mon;
	public static final WeekDayEnum Tues;
	public static final WeekDayEnum Wed;
	public static final WeekDayEnum Thu;
	public static final WeekDayEnum Fri;
	public static final WeekDayEnum Sat;
	public static final WeekDayEnum Sun;
	private static final WeekDayEnum ENUM$VALUES[];

	private WeekDayEnum(String s, int i)
	{
		super(s, i);
	}

	public static WeekDayEnum[] values()
	{
		WeekDayEnum aweekdayenum[];
		int i;
		WeekDayEnum aweekdayenum1[];
		System.arraycopy(aweekdayenum = ENUM$VALUES, 0, aweekdayenum1 = new WeekDayEnum[i = aweekdayenum.length], 0, i);
		return aweekdayenum1;
	}

	public static WeekDayEnum valueOf(String s)
	{
		return (WeekDayEnum)Enum.valueOf(cn/tjd/enumtest/WeekDayEnum, s);
	}

	static 
	{
		Mon = new WeekDayEnum("Mon", 0);
		Tues = new WeekDayEnum("Tues", 1);
		Wed = new WeekDayEnum("Wed", 2);
		Thu = new WeekDayEnum("Thu", 3);
		Fri = new WeekDayEnum("Fri", 4);
		Sat = new WeekDayEnum("Sat", 5);
		Sun = new WeekDayEnum("Sun", 6);
		ENUM$VALUES = (new WeekDayEnum[] {
			Mon, Tues, Wed, Thu, Fri, Sat, Sun
		});
	}
}

哇,你会发现这个类和我们当初写的WeekDay类怎么很相似呢?

反编译后的关注点:

1. 枚举类默认继承java.lang.Enum类,而不是传统类的Object父类。

2. 类名用final修饰,也就是说枚举类不能有子类继承它。

3. 构造器是私有的。

细细体会反编译的源码。。。。。

枚举类的其他用法

这里我值提供一些思路:

1. 枚举类可以用于做常量,也就是我们上面所描述的。

2. 枚举类可以写单例模式,并且可以防止通过反射或序列化进行单例攻击。

       参考这篇文章:https://www.cnblogs.com/chiclee/p/9097772.html

3. 可以用在switch语句中做分支判断。。

等.....

原创不易啊!!走过路过不要错过,帮博主点个赞吧,嘻嘻!!

 

猜你喜欢

转载自blog.csdn.net/tianjindong0804/article/details/86421108
今日推荐