黑马程序员--02.JDK5部分新特性--02【枚举】

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学习型技术博客、期待与您交流! ------------

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值