--------- android培训、java培训、期待与您交流!----------

一、为什么要有枚举?

  • 问题:要定义季节、星期向或性别的变量,该怎么定义?假设用1-4分别表示春、夏、秋、冬,但有人可能会写成int SEASON_SPRING = 0;或即使使用常量方式也不无法阻止意外,因为int型的数据是可以参与运算的。

  • 枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。

  • 枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。

二、那么该如何用普通类实现枚举功能呢?

以定义一个Seanson类来模拟枚举功能。

①私有化构造方法,加private

②每个元素分别用一个公有的静态成员变量表示,public static ,再加上final表示不能派生子类。

③可以有若干公有方法或抽象方法。

④采用抽象方法定义nextSeason就是将大量的if.else语句转移成了一个个独立的类。

如下代码:

package com.itheima.blog;
public class Season {private final String name;//分别创建Season的四个子类,并用public static final修饰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 Season nextSeason(){if (this == SPRING) {return SUMMER;}if (this == SUMMER) {return FALL;}if (this == FALL) {return WINTER;}if (this == WINTER) {return SPRING;}return null;/*  经测试,switch不能使用此方法,this会报错;* switch(this){case SPRING:return SUMMER;case SUMMER:return FALL;case FALL:return WINTER;case WINTER:return SPRING;default:return null;*/}//将构造方法私有化private Season(String name){       this.name = name;}//因为枚举值是固定的,所以只提供获取方法。public String getName(){return this.name;}
}

也可以将以上代码改成抽象方法的方式:

如:

package com.itheima.blog;
//因为声明了抽象方法,所以该类也必须显示声明为抽象类。
public abstract class Season {//定义一个field该field也是不能被直接访问的,并且不可变。private final String name;//创建一个Season对象的匿名实例,并内部提供方法。该方法称为抽象方法public static final Season SPRING = new Season("春天"){public Season nextSeason(){return SUMMER;}};public static final Season SUMMER = new Season("夏天"){public Season nextSeason(){return FALL;}};public static final Season FALL = new Season("秋天"){public Season nextSeason(){return WINTER;}};public static final Season WINTER = new Season("冬天"){public Season nextSeason(){return SPRING;}};//声明该类的抽象方法public abstract Season nextSeason();   //将构造方法私有化private Season(String name){       this.name = name;}//因为枚举值是固定的,所以只提供获取方法。public String getName(){return this.name;}
}

测试类:

package com.itheima.blog;
public class SeasonTest {public static void main(String[] args) {Season s = Season.WINTER;System.out.println(s.nextSeason().getName());//结果都是春天}
}

三、枚举类的基本应用

和class关键字声明的类一样,一个Java源文件中最多只能定义一个public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同。

它具有如下几个特点:

①枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是继承java.lang.Object类,其中java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。

②使用enum定义、非抽象的枚举类默认会使用final修饰,因此枚举类不能派生子类。

//经测试:发现不能显式用final修饰。

③枚举类的构造器只能使用private访问修饰符,如果省略了构造器的访问控制符,则默认使用

private修饰;如果强制指定访问控制符,则只能指定private修饰符。

④枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无须程序员显式添加。

⑤所有枚举类都提供了一个values方法,该方法用来遍历该枚举类的所有的枚举实例。

下面以例子来说明,枚举类的使用:

1、例子一(最简单的枚举类):

package com.itheiam.blog;
public enum Season
{//必须定义在第一行,元素之间用,号隔开,后面可以加;也可不加SPRING,SUMMER,FALL,WINTER
}
class SeasonTest
{public static void main(String[] args){//直接获取Season的实例,并返回Season对象,说明有static修饰。Season s = Season.FALL;//下面演示一些方法System.out.println(s.name());//打印FALLSystem.out.println(s.toString());//打印FALL//所以toString方法和name()方法效果是一样的。System.out.println(s.ordinal());//打印2,说明返回的是所谓的角标。//静态方法//将字符串转成对应的枚举实例,很重要。System.out.println(Season.valueOf("SUMMER"));//SUMMERSystem.out.println(Season.valueOf(Season.class, "FALL"));//FALL//遍历该枚举类的所有实例。for (Season season : Season.values()) {System.out.println(season);}}
}

2、例子二(枚举类的Field、方法和构造器):

package com.itheiam.blog;
public enum Season2
{  //如果枚举值后有参数,则必须加最后必须加";"否则会报错SPRING("春天"),SUMMER("夏天"),FALL("秋天"),WINTER("冬天");//这样定义也是可以的。//春天("SPRING"),夏天("SUMMER"),秋天("FALL"),冬天("WINTER");//应该将枚举类的Field用private final修饰/*因为我们将所有的Field都用final修饰符来修饰,所以必须在构造器里为这些Field指定初始值(或者在定义Field时指定默认值,或者在初始化块中指定初始值,但这两种情况不常见)因此,我们需要为枚举类显式定义带参数的构造器。*/private final String name;//显式声明私有化的构造方法private Season2(String name){this.name = name;}//获取枚举值,也就是枚举实例对应的名称public String getName(){return this.name;}
}
class SeasonTest2
{public static void main(String[] args){//通过枚举的实例对象来获取枚举值String str = Season2.FALL.getName();System.out.println(str);//秋天System.out.println(Season2.SPRING);//SPRING//通过Enum的静态方法valueOf方法来获取指定枚举类的枚举值。Season2 s = Enum.valueOf(Season2.class, "FALL");System.out.println(s.getName());//秋天}
}

3、例子三(实现接口的枚举类):

package com.itheiam.blog;
//定义一个接口,用来获取Season信息
interface SeasonInfo
{void info();
}
//让枚举类实现接口
public enum Season3 implements SeasonInfo
{//如果枚举值后有参数,则必须加最后必须加";"否则会报错SPRING("春天"),SUMMER("夏天"),FALL("秋天"),WINTER("冬天"); //应该将枚举类的Field用private final修饰private final String name;//显式声明私有化的构造方法private Season3(String name){this.name = name;}//获取枚举值,也就是枚举实例对应的名称public String getName(){return this.name;}//因为实现了SeasonInfo接口,所以必须实现其方法public void info(){System.out.println("这是一个获取季节信息的方法!");}
}
class SeasonTest3
{public static void main(String[] args){//通过Enum的静态方法valueOf方法来获取指定枚举类的枚举值。Season3 s1 = Enum.valueOf(Season3.class, "FALL");System.out.println(s1.getName());s1.info();Season3 s2 = Enum.valueOf(Season3.class, "WINTER");System.out.println(s2.getName());s2.info();}
}
/*-------------------------------
打印结果:秋天这是一个获取季节信息的方法!冬天这是一个获取季节信息的方法!
-------------------------------*/

由以上例子可以看出,如果由枚举来实现接口里的方法,则每个枚举值在调用方法时都有相同的行为方式(因为方法体完全一样)。如果需要每个枚举值在调用该方法时呈现出不同的行为方式,则可以让每个枚举实例分别来实现该方法,从而让不同的枚举值调用该方法时具有不同的行为方式。程序如下:

package com.itheiam.blog;
interface SeasonInfo2
{void info();
}
//让枚举类实现接口
public enum Season4 implements SeasonInfo2
{//如果枚举值后有参数,则必须加最后必须加";"否则会报错SPRING("春天"){public void info(){System.out.println("红豆生南国,春来发几枝。愿君多采撷,此物最相思。");}},SUMMER("夏天"){public void info(){System.out.println("垂緌饮清露,流响出疏桐。居高声自远, 非是藉秋风。");}},FALL("秋天"){public void info(){System.out.println("解落三秋叶,能开二月花。过江千尺浪,入竹万竿斜。");}},WINTER("冬天"){public void info(){System.out.println("墙角数枝梅,凌寒独自开。遥知不是雪,为有暗香来。");}}; //应该将枚举类的Field用private final修饰private final String name;//显式声明私有化的构造方法private Season4(String name){this.name = name;}//获取枚举值,也就是枚举实例对应的名称public String getName(){return this.name;}
}
class SeasonTest4
{public static void main(String[] args){//通过Enum的静态方法valueOf方法来获取指定枚举类的枚举值。Season4 s1 = Enum.valueOf(Season4.class, "FALL");System.out.println(s1.getName());s1.info();Season4 s2 = Enum.valueOf(Season4.class, "WINTER");System.out.println(s2.getName());s2.info();}
}
/*--------------------------------
打印结果:秋天解落三秋叶,能开二月花。过江千尺浪,入竹万竿斜。冬天墙角数枝梅,凌寒独自开。遥知不是雪,为有暗香来。
--------------------------------*/

4、例子四(包含抽象方法的枚举类):

package com.itheiam.blog;
/*虽然枚举内部定义了抽象方法,但这里不能使用abstract关键字将枚举类
定义成抽象类(因为系统自动会为它添加abstract关键字),否则会报错。*/
//public abstract enum Season5
public enum Season5
{SPRING("春天"){public void describeInfo(){System.out.println("红豆生南国,春来发几枝。愿君多采撷,此物最相思。");}},SUMMER("夏天"){public void describeInfo(){System.out.println("垂緌饮清露,流响出疏桐。居高声自远, 非是藉秋风。");}},FALL("秋天"){public void describeInfo(){System.out.println("解落三秋叶,能开二月花。过江千尺浪,入竹万竿斜。");}},WINTER("冬天"){public void describeInfo(){System.out.println("墙角数枝梅,凌寒独自开。遥知不是雪,为有暗香来。");}};//为了好跟前面的方法比较,继续定义一个Fieldprivate final String name;/*因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法实现,否则将出现编译错误。*/public abstract void describeInfo();private Season5(String name){this.name = name;}public String getName(){return this.name;}
}
class SeasonTest5
{public static void main(String[] args){//通过Enum的静态方法valueOf方法来获取指定枚举类的枚举值。Season5 s1 = Enum.valueOf(Season5.class, "FALL");System.out.println(s1.getName());s1.describeInfo();Season5 s2 = Enum.valueOf(Season5.class, "WINTER");System.out.println(s2.getName());s2.describeInfo();}
}
/*-------------------------------
打印结果:秋天解落三秋叶,能开二月花。过江千尺浪,入竹万竿斜。冬天墙角数枝梅,凌寒独自开。遥知不是雪,为有暗香来。
-------------------------------*/

四、其它

  • 当枚举只有一个成员时,就可以作为一种单例的实现方式。

--------- android培训、java培训、期待与您交流!----------

转载于:https://blog.51cto.com/1139347837/1252931

黑马程序员-Java基础加强之枚举相关推荐

  1. 黑马 程序员——Java基础---流程控制

    黑马程序员--Java基础---流程控制 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 Java提供了两种基本的流程控制结构:分支结构 ...

  2. 黑马 程序员——Java基础---IO(下)

    黑马程序员--Java基础---IO(下) ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供 ...

  3. 黑马程序员--Java基础加强篇

    开发工具使用 --------------------------------------------------------------------------------------------- ...

  4. 黑马程序员-Java基础知识预备之Java流程控制与数组

    -------- android培训.java培训.期待与您交流!---------- 本博文涉及的主要内容如下: if语句 switch语句 循环结构 循环结构的控制 数组类型 数组在内存中的运行机 ...

  5. 黑马程序员-Java基础:面向对象(上)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.面向对象概述 当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高.可随着需求的 ...

  6. 黑马程序员—java基础总结1

    ------- android培训.java培训.期待与您交流! ---------- 一:java概述: 1991 年Sun公司的James Gosling等人开始开发名称为 Oak 的语言,希望用 ...

  7. 黑马程序员 — JAVA基础 — 内部类、异常

    -----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 一.内部类 1.概念: 把类定义在另一个类的内部,该类就被称为内部类. Eg:把 ...

  8. 黑马程序员-Java基础:设计模式总结

    --Java培训.Android培训.iOS培训..Net培训.期待与您交流! -- Java基础部分设计模式 一.设计模式概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的 ...

  9. 黑马程序员----------------java基础-----------------Map集合

     ------- <a href="http://www.itheima.com" target="blank">android培训</a ...

最新文章

  1. Windows Server 2012 系统群集
  2. 全排列 ---java
  3. html弄多个按钮_html+css3实现多个表单按钮美化效果
  4. 你真的懂TensorFlow吗?Tensor是神马?为什么还会Flow?
  5. 统计一行文本的单词个数_word操作技巧:不同情况的文字统计方法
  6. void符合c语言用户标识吗,1以下可用作C语言用户标识符的是()。void,define,.doc...
  7. linux mint 18安装中文,无法在Linux Mint 18.1“Serena”下安装pyFFTW
  8. web.config中的ExtensionlessUrlHandler-Integrated-4.0
  9. winrar大全+压缩
  10. 表白代码大全,快来向你的ta表白吧~~~
  11. markdown下载及基本语法
  12. 教你设置QQ空间个性签名档
  13. 主程玩失踪,公司蒸发600w,创始人秒变打工仔(含视频)
  14. flask中'bool' object has no attribute '__call__'问题
  15. 逆序字符串 和 字符串的逆序输出 的区别~
  16. 2014.7.14 有用的网址
  17. 如何取消qq的“小世界”功能
  18. NPOI 读取空Excel 空单元格报错的问题
  19. word2vec原理
  20. Java 计算任意两天之间相隔的天数

热门文章

  1. Win10 adb pull指定的文件
  2. inkscape如何裁剪_Inkscape进阶教程
  3. css网页技术的网页交互方法
  4. 10kv电压互感器型号_10KV电压互感器的选型与保护7页
  5. 自己制作优化大师(win32 SDK)
  6. python连接微信接口开发教程_Python调用微信公众平台接口操作示例
  7. chrome设置微信ua_用Chrome在电脑上模拟微信浏览器 - 雪山玉龙 - 博客园
  8. 工程材料(2)铁碳相图
  9. 新基建开航之际,百度“黄埔学院”发力培养“AI船长”
  10. python爬虫实战 获取豆瓣排名前250的电影信息--基于正则表达式