JDK5部分新特性----2
模拟枚举 JDK5枚举
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1. 普通类模拟枚举类
1). 使用枚举类型的原因
枚举的优势:可以让某个变量的取值只能为若干固定取值中的一个,否则编译器会报错!!
【注意】枚举可以让编译器在编译阶段控制程序的非法输入。而普通变量却没有办法在编译阶段达到这样一个功能。(枚举变量相比于普通变量的优势)
2). 普通类模拟枚举的步骤
(1). step 1: 私有化构造函数
【小总结】模拟枚举类、单例模式、工具类的第一步都是私有化构造函数
私有化的原因:即外部使用这个类的时候,外部不能自行创建这个类的对象。这样枚举类的取值就在枚举类定义的时候就会固定下来。不会出现枚举中定义没有的取值
(2). step 2: 每一个枚举成员表示成一个全局常量(public staticfinal) (自定义枚举的常量离散取值)
(3). step3: 可以定义若干公共方法和抽象方法,由子类成员的内部类实现。
{1}.可以定义成具体方法
{2}.可以定义成抽象方法
3). 模拟方式I ----将枚举中的自定义方法自定义成具体方法
(1). 举例代码
/*
* 用Java的普通类来模拟Java中的枚举类型
* */
public class WeekDay {
//Step1. 私有化构造方法
private WeekDay(){}
//Step2. 每一个元素为全局常量,public static final ----枚举中的常量元素
public static final WeekDay MON =new WeekDay();
public static final WeekDay SUN =new WeekDay();
//Step3. 自定义的若干方法
public WeekDay nextDay(){
if(this == MON) //MON为枚举常量
return SUN;
return MON;
}
/*
缺点:如果枚举常量值非常多的时候,这个方法中会存在大量的if...else if... else
*/
public String toString(){
return (this==SUN)? "SUN": "MON";
}
}
/*
缺点:如果枚举常量值非常多的时候,这个方法中会存在大量的if...else if... else
*/
【自定义方法为具体方法的劣势】自定义方法会因为全局常量数量过多而出现非常臃肿的分支语句代码。
4). 模拟方式II ----将枚举中的自定义方法自定义成具体方法
(1). 简化模拟枚举类中的非静态方法
【分析解决的办法】对于使用到每个枚举常量值的非静态方法,由于内部代码的功能都是一样的,但是涉及到不同的数据,所以将这些方法功能相同(方法名不变)但是实现不同的方法集体向上抽取成一个抽象方法abstract。由于抽象方法的存在导致抽象方法所在的类必须是抽象类
(2). 简化之后模拟枚举类的代码
package cn.itcast.day1;
/*
* 用Java的普通类来模拟Java中的枚举类型
* */
public abstract class WeekDayII {
//Step1. 私有化构造方法
private WeekDayII(){}
// 采用匿名内部类
public static final WeekDayII MON =new WeekDayII(){
@Override
public WeekDayII nextDay() {
return SUN;
}
public String toString(){
return "MON";
}
};
public static final WeekDayII SUN =new WeekDayII(){
@Override
public WeekDayII nextDay() {
return MON;
}
public String toString(){
return "SUN";
}
};
public abstract WeekDayII nextDay();
}
【测试类】
WeekDayII weekDay =WeekDayII.MON;// 现在是多态的调用形式
//左边是抽象父类 右边是实现//父类的子类(匿名内部类实现)
System.out.println(weekDay.nextDay());
2. JDK5 枚举
1). JDK5枚举的基本知识
(1). 定义枚举
[1]. 定义枚举类的关键字是enum
举例:
public enum WeekDayEnum {
SUN, MON, TUE, WED, THU, FRI, SAT
}
class TestEnum{
public static void main(String[] args) {
WeekDayEnumweekDay =WeekDayEnum.MON;
System.out.println(weekDay);
}
}
[2]. JDK5引入枚举关键字enum和枚举的好处
public enum WeekDayEnum {
SUN, MON, TUE, WED, THU, FRI, SAT
}
【枚举关键字enum的好处】
采用enum,就可以直接定义枚举类型的常量来替代上面的模拟枚举类的中的书写内容
<1> 省略public static final的书写形式
<2>. 省略私有化构造函数
<3>. 省略采用匿名内部类创建枚举常量的成员
以上的工作全部封装到enum关键字中,大大简化了书写。
e,g. 这里面 SUN 直接替代了
public static final WeekDayII SUN =new WeekDayII(){
@Override
public WeekDayII nextDay() {
return MON;
}
public String toString(){
return "SUN";
}
};
【枚举的好处】
编译期间出现非法值,编译无法与通过
***枚举关键字大大简化了使用枚举功能的开发
(2). JDK5中的枚举和普通类的关系
[1]. 枚举类型是一种特殊的类
[2]. 枚举中的枚举元素全部是全局常量
{1}. 枚举元素实际上是这个枚举类型的引用全局常量
{2}. 这些引用全局常量由enum保证显式初始化之后,指向了枚举类型的一个匿名内部子类实例
{3}. 定义枚举元素时候不用书写类型,由enum关键字保证这个常量的类型
(3). 枚举成员的常用方法
【获取功能方法】
[1]. 获取成员的名字:name() 默认值就是枚举成员的标示符名字(非静态)
[2]. 获取成员在所有枚举元素中的排名:ordinal() 按照定义时候书写顺序的排行(非静态)
[3]. 获取所有枚举成员构成的数组:values() (静态)
【转换功能方法】
将字符串转化为枚举类型的元素:valueOf(Stringname)
3. 带有构造函数的枚举(JDK5)
(1). 枚举类型的书写规则
[1]. 枚举成员常量必须位于枚举类的所有其他成员之前。
e.g.如果这个枚举类型有构造函数,其他方法。则要求枚举成员常量位于这些方法之前
[2]. 枚举成员常量列表之后如果存在枚举类的其他非枚举元素成员,则必须和前面的枚举成员常量列表用;隔开。
(2). JDK中枚举构造方法的定义和调用方式
[1]. 定义枚举构造方法的时候,应该必须注意的地方
枚举类的构造方法必须使用private做访问修饰符。
[2]. 枚举构造方法的调用
在枚举成员之后加上一对( )来调用相应的构造函数
{1}. 如果枚举成员后面跟的是空的() ,调用的是枚举类的空参的构造函数。
默认定义的枚举常量【没有添加任何( )】和仅仅添加没有参数的()是一样的,调用的是默认枚举类型的空参数构造函数
{2}. 如果枚举成员后面跟的是带有实参值的 ( ),则这个时候,调用指定枚举类型的构造函数。
{3}. 由于枚举成员默认的类型是public static final类型,所以枚举类型一加载到内存的时候,相应的静态枚举成员就会立刻调用枚举类的构造函数。
(3). 带有构造方法的枚举类型的举例
public enum WeekDay {
//每一个枚举元素都相当于该类的对象的引用
SUN(1), MON(2), TUE(3), WED(4), THU, FRI, SAT;
private WeekDay(){
System.out.println("The first constructor...");
}
private WeekDay(int day){
System.out.println("The second constructor..."+ day);
}
}
【测试类:综合举例】
*************************************
WeekDay weekDay =WeekDay.FRI;
/*非静态方法的使用
* */
System.out.println(weekDay);
System.out.println(weekDay.name());
System.out.println(weekDay.ordinal());
/*枚举类静态方法的使用* */
System.out.println(WeekDay.valueOf("SUN"));
System.out.println("WeekDay中元素的长度:" +WeekDay.values().length);
WeekDay[] weeks =WeekDay.values();
for(WeekDay weekDayx: weeks){
System.out.print(weekDayx+ " ");
}
***********************************
打印结果
4. 带有抽象方法的枚举(JDK5)
(1). 枚举类型含有抽象方法的注意事项
[1]. 当枚举类型中有抽象方法的时候,在定义枚举类成员的时候,不能直接定义或者仅仅定义调用哪个构造函数的枚举成员,必须同时要求枚举成员实现这个枚举类型的抽象方法,否则编译报错。
[2]. 含有抽象方法的类是抽象类。如果枚举类内部含有抽象方法,本应在枚举类的前面加上abstract。但是enum这个关键字为我们做了这些。所以,直接可以在枚举类型中定义抽象方法而不用为enum的类再添加abstract关键字。
(2). 枚举类型中含有抽象方法的举例
[1]. 定义枚举成员常量的时候没有实现里面的抽象方法,编译报错
[2]. 实现了枚举类中抽象方法的代码
package cn.itcast.day2;
public enum TrafficLamp {
RED(30){
@Override
public TrafficLamp nextLamp() {
return GREEN;
}
},
GREEN(45){
@Override
public TrafficLamp nextLamp() {
return YELLOW;
}
},
YELLOW(5){
@Override
public TrafficLamp nextLamp() {
return RED;
}
};
//每种灯持续照亮的时间长度
private int durTime;
public abstract TrafficLamp nextLamp();
private TrafficLamp(){}
private TrafficLamp(int durTime){
this.durTime =durTime;
}
}
[3]. 对上面代码的解释:
5. 枚举和单例模式的关系
如果枚举只有一个成员,那么这个枚举类型就可以作为单例模式的一种实现方式
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------