------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
第一讲 枚举
一:枚举概述
什么是枚举?现实生活我们肯能会经常碰到,今天星期几?一个星期是固定的,就7天。再比如,一年有几个季节,这些固定的数在java中该如何表示呢?用常量1-7表示星期几?用常量1-4表示“春夏秋冬”?显然这不是好的方法。原因有如下几点:
1)类型不安全,如果用数字表示,则可实现算数运算,显然不合理
2)没有命名空间:比如,在使用Spring(春天时)必须加前缀Season,否则容易和其他类中常量混淆
3)打印输出不够合理,比如用1代表Spring时,打印输出的是1,显然不直观
而java也从JDK1.5以后给我们提供了一个更好的方法来表示这些固定的常用的数——即:枚举,
二:手动实现枚举类
如需手动实现枚举类,可按如下要求设计
1) 通过Private将构造函数封装起来
2) 把这个类所有要实现的字段用public static final 修饰起来
3) 如果有必要则提供外界一些静态方法,可以按某种特定格式来获取与之匹配的实例
public class Season
{
//把Season类定义成不可变的,将其属性也定义成final
private final String name;
private final String desc;
public static final Season SPRING = new Season("春天" , "趁春踏青");
public static final Season SUMMER = new Season("夏天" , "夏日炎炎");
public static final Season FALL = new Season("秋天" , "秋高气爽");
public static final Season WINTER = new Season("冬天" , "围炉赏雪");
public static Season getSeaon(int seasonNum)
{
switch(seasonNum)
{
case 1 :
return SPRING;
case 2 :
return SUMMER;
case 3 :
return FALL;
case 4 :
return WINTER;
default :
return null;
}
}
//将构造器定义成private访问权限
private Season(String name , String desc)
{
this.name = name;
this.desc = desc;
}
//只为name和desc属性提供getter方法
public String getName()
{
return this.name;
}
public String getDesc()
{
return this.desc;
}
}
测试自己编写的枚举类:
<span style="white-space:pre"> </span><pre name="code" class="java">public class TestSeason
{
public TestSeason(Season s)
{
System.out.println(s.getName() + ",这真是一个"+ s.getDesc() + "的季节");
}
public static void main(String[] args)
{
//直接使用Season的FALL常量代表一个Season对象
new TestSeason(Season.FALL);
}
}
由此可见,利用枚举可以避免创建对象的随意性,使数据得到更好的封装!
三:JDK1.5以后的枚举
自己创建枚举对象比较麻烦,有没有更快捷的方式呢,Java从JDK1.5以后就给大家提供了枚举关键字:enum ,使大家可以更快速的创建枚举对象。
enum 和class interface 关键字等同。
使用enum 创建的枚举类和普通类相似,但也有区别,区别如下:
1)使用enum 创建的非抽象的枚举类默认使用final修饰,因此,枚举类不可有子类
2)使用enum定义的枚举类默认继承Java.Lang.Enum类
3)枚举类的构造器只能是Private,默认就是Private
4) 枚举类的所有实例必须在第一行显示列出,默认会添加public static final 修饰符
枚举类一般都设计成不可变类! 为了安全。因此枚举类中的Field值都应该用private final 来修饰!为此,则在构造器中去初始化这些变量(因为在初始化代码块和定义Field时指定默认值一般在枚举类中都不会用到) 如下定义一个男,女枚举
public enum Gender
{
//此处的枚举值必须调用对应构造器来创建
MALE("男"),FEMALE("女");
private String name;
//枚举类的构造器只能使用private修饰
private Gender(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
}
MALE("男") 其实就相当于:public static final Gender MALE =new Gender("男");
四:实现接口的枚举类
枚举类和普通类一样,可以实现接口,实现接口的方法可以在枚举类里直接实现,如下:
public class EnumTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Season.Spring);
System.out.println(Season.Spring.Description());
System.out.println(Season.Summer);
System.out.println(Season.Summer.Description());
}
public interface IDes
{
String Description();//描述
}
enum Season implements IDes
{
Spring("春天"),
Summer("夏天");
@Override
public String Description() {
return "这是一个季节";
}
private final String name;
private Season(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
}
输出如下:
Spring
这是一个季节
Summer
这是一个季节
由此可见,如果实现接口的方法在枚举类里实现,那么每个枚举值调用此方法时,显示的结果一样,显然在大多数情况下,这不是我们想要的结果,我们想要每个枚举值调用方法时显示不同的结果,那怎么办?我们学过匿名内部类,同样,在枚举中也可以利用匿名内部类来完成我们想要的结果,如下:
public class EnumTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Season.Spring);
System.out.println(Season.Spring.Description());
System.out.println(Season.Summer);
System.out.println(Season.Summer.Description());
}
public interface IDes
{
String Description();//描述
}
enum Season implements IDes
{
Spring("春天")
{
@Override
public String Description()
{
return "这是一个春暖花开的季节";
}
},
Summer("夏天")
{
public String Description()
{
return "这是一个炎热的季节";
}
};
private final String name;
private Season(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
}
}
结果如下:
Spring
这是一个春暖花开的季节
Summer
这是一个炎热的季节
注意:此时枚举类的修饰符是abstract ,此时的枚举类相当于一个抽象枚举类。只有当定义一个非抽象枚举类时,修饰符才会是:final !!!
五:包含抽象方法的枚举类
上题也可不用接口,而在枚举类里定义一个抽象方法,有各个枚举值的匿名内部类去实现,代码如下:
public class EnumTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Season.Spring);
System.out.println(Season.Spring.Description());
System.out.println(Season.Summer);
System.out.println(Season.Summer.Description());
}
enum Season
{
Spring("春天")
{
@Override
public String Description()
{
return "这是一个春暖花开的季节";
}
},
Summer("夏天")
{
public String Description()
{
return "这是一个炎热的季节";
}
};
public abstract String Description();//定义一个抽象方法,如果不加这句,直接在内部类里写方法,则编译通不过,说明:枚举类必须提供枚举值使用方法的规范
private final String name;
private Season(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
}
}
结果如下:
Spring
这是一个春暖花开的季节
Summer
这是一个炎热的季节
枚举类中包含抽象方法时,枚举类不能显示指定abstract 修饰符,系统会自动添加!