一,Java枚举其实本质是一种特殊的类
特殊在于:对于一般的类在定义时是不确定实际使用的时候到底会创建多少个对象,可以具需求不定量的创建其类对象。而枚举是在类定义的时候可以确定对象个数的( 也就是说可以一一列举出来的,固定的数个对象 )。
二,通过普通的类描述,简单模拟枚举的特点,从而理解枚举
1.枚举的特点是对象个数是确定的,所以首先我们需要确保构造方法私有,才能确定对象不能随意被创建。
2.再则就是用当前类对象作为属性,并且使用final和static特征修饰符修饰,这样就可以固定对象不被更改且唯一存在。
如下:
public class Day{
public static final Day monday = new Day();
public static final Day tuesday = new Day();
public static final Day wednesday = new Day();
public static final Day thursday = new Day();
public static final Day friday = new Day();
public static final Day saturday = new Day();
public static final Day sunday = new Day();
private Day(){
}
}
访问:
public class Main {
public static void main(String[] args){
Day day = Day.monday;
}
}
上面模拟的是一周的7天,星期一到星期天,从代码便可以看出描述了确定对象个数的一个类了。
如果在真正使用枚举枚举类如何描述这7天呢?
public enum Day{
monday,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday
}
访问:
public class Main {
public static void main(String[] args){
Day day = Day.monday;
}
}
将class关键字改为enum就可了,然后作为对象的属性名直接列举出来用逗号隔开,这样就描述出来了,是不是觉得和自己描述的有点像呢,其实改为enum关键字之后,其实这个类就是一个枚举类了,枚举类默认继承于至Enum类。
上面这里简单作为一个理解性的引入过程,枚举的真正使用及原理并不是如此,接着往下看
三,枚举类的深入理解
翻看enum类型父类Enum源码:
可以看到enum类型是jdk 1.5之后才出现的,实现了Comparable接口和Serializable接口。
具有两个私有属性及对应的共有获取方法。
name:表示枚举对象的名字,默认为列举时写的名字。
ordinal:表示列举枚举对象时候的顺序,从0开始记录。
还有几个常用方法:
其中:
compareTo() 方法是重写至Object的,用于根据列举顺序(ordinal)比较先后。返回结果为顺序之差。
valueOf() 方法用于通过枚举对象名(name)定位获取对应的枚举对象。
toString() 重写了至Object的,返回的是枚举对象名字。并且自己定义枚举的时候还可以进行重写。
hashCode() 重写至Object的,但是实际上还是调用了Object的hashCode()方法。底层调用了本地其他语言的方法。
equals() 重写至Object的,用于比较对象是否相等,这里比较的是地址引用。
clone() 重写至Object的,这里直接抛出异常,说明枚举类型不支持clone。
此外还有一个源码没有写出的一个方法: values() 。用于获取所有的枚举对象,返回结果为当前枚举类型的数组。
eg:(这里测试常用方式)
public enum Day {
monday,tuesday,wednesday,thursday,friday,saturday,sunday;
public static void main(String[] args) {
System.out.println("---------------------直接访问对象-------------------------");
Day day = Day.monday;
System.out.println(day.name()+"-"+day.ordinal());
System.out.println("---------------------通过名字访问对象---------------------");
Day day2 = Day.valueOf("tuesday");
System.out.println(day2.name()+"-"+day2.ordinal());
System.out.println("---------------------未知名字,获取所有对象------------------");
Day[] days = Day.values();
for(Day d : days){
System.out.println(d.name()+"-"+d.ordinal());
}
}
}
输出结果:
---------------------直接访问对象--------------------------
monday-0
---------------------通过名字访问对象----------------------
tuesday-1
---------------------未知名字,获取所有对象-----------------
monday-0
tuesday-1
wednesday-2
thursday-3
friday-4
saturday-5
sunday-6
Process finished with exit code 0
一一列举的枚举类型,内部其实都会创建帮我们创建对应的对象。
三,和一般的类一样,在描述一个枚举类的时候,自己可以定义一些属性和方法。
:需要注意的是构造方法必须是私有的(否者报红线(能够被自动检测到)),为了确保对象个数确定,并且不能在外部创建对象。这里第一点有引述过。
eg:
public enum Day {
monday("周一","学习java!"),
tuesday("周二","学习java!"),
wednesday("周三","学习java!"),
thursday("周四","学习java!"),
friday("周五","学习java!"),
saturday("周六","学习java!"),
sunday("周日","出门溜达溜达~");
private String description;
private String activity;
private Day(String description, String activity) {//必须为私有得构造方法
this.description = description;
this.activity = activity;
}
private Day(){}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getActivity() {
return activity;
}
public void setActivity(String activity) {
this.activity = activity;
}
}
public class Main{
public static void main(String[] args) {
Day[] days = Day.values();
for(Day d : days){
System.out.println("["+d.name()+"-"+d.ordinal()+"] ============>"+"今天是"+d.getDescription()+","+d.getActivity());
}
}
}
输出:
[monday-0] ============>今天是周一,学习java!
[tuesday-1] ============>今天是周二,学习java!
[wednesday-2] ============>今天是周三,学习java!
[thursday-3] ============>今天是周四,学习java!
[friday-4] ============>今天是周五,学习java!
[saturday-5] ============>今天是周六,学习java!
[sunday-6] ============>今天是周日,出门溜达溜达~
Process finished with exit code 0
四,使用实例
枚举类型在jdk1.5出现之后,开始用于switch条件分支语句了。下面以switch语句来进行举例:——> 以上面描述的那个枚举Day类型为例
public class Main{
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请选择输入:(monday/tuesday/wednesday/thursday/friday/saturday/sunday)");
String name = input.nextLine();
String things = "";
try {
Day day = Day.valueOf(name);
switch (day){
case monday:things = "今天是"+day.getDescription()+","+day.getActivity();break;
case tuesday:things = "今天是"+day.getDescription()+","+day.getActivity();break;
case wednesday:things = "今天是"+day.getDescription()+","+day.getActivity();break;
case thursday:things = "今天是"+day.getDescription()+","+day.getActivity();break;
case friday: things = "今天是"+day.getDescription()+","+day.getActivity();break;
case saturday:things = "今天是"+day.getDescription()+","+day.getActivity();break;
case sunday:things = "今天是"+day.getDescription()+","+day.getActivity();break;
default:things = "无信息";
}
}catch (IllegalArgumentException e){
System.out.println("输入有误!!!");
}
System.out.println(things);
}
}
测试: