枚举也就是一一列举,常用来表示那些可以明确范围的集合,比方说性别,季节,星期,月份等。

在 JDK 1.5 才出现枚举类,在没有出现枚举类之前,我们要表示几个确定的值通常会使用常量来表示,形如

  1. public static final Integer SPRING = 1;
  2. public static final Integer SUMMER = 2;
  3. public static final Integer FALL = 3;
  4. public static final Integer WINTER = 4;

我们可以使用枚举类来表示,这也就是最简单的枚举。

  1. enum Season{
  2. SPRING,SUMMER,FALL,WINTER;
  3. }

那么枚举类和定义常量相比有什么优势呢?

安全,我们看上面的代码可以知道,使用常量表示的季节都是 Integer 类型的,而这个类型的数据范围太大了,而使用枚举就限制了数据的域。枚举可以理解为几个常量的集合,数据不太会改变,使用枚举之后语义更加明确,因为数据域不大。

关于枚举类,有几点需要注意:

  1. enum 和 class ,interface 的地位一样

  2. 使用 enum 定义的枚举类默认继承了 java.lang.Enum,而不是继承 Object 类。枚举类可以实现一个或多个接口,不能再继承其他类了。

  3. 枚举类的所有实例都必须放在第一行展示,不需使用 new 关键字,不需显式调用构造器。自动添加 public static final 修饰。

  4. 枚举类的构造器只能是私有的。

关于第 4 点,我要说枚举类的定义是单例模式的,单例模式要求构造器私有化,不允许在外部创建新的对象,你想呀,枚举类的作用就是准确的表示出同一类别下的不同数据。在我们定义的时候已经创建好了,所以跟本不需要也不能在外部继续创建新的对象。故,需要将构造器私有化。

枚举类说的通俗点就是被阉割的类,我们使用类可以创建对象,而枚举类在定义的时候就会指定创建的对象有哪些。你没有显示的写代码创建,不过是由于 JVM 自动给你加上去了。待会看看枚举类被反编译之后的情况就会理解。

枚举类中可以定义属性和方法。

  1. enum Season{
  2.  
  3. SPRING("春天","一年之计在于春"),SUMMER("夏天","夏天好热 ~ "),
  4. FALL("秋天","秋水共长天一色"),WINTER("冬天","冬天好冷 ~ ");
  5.  
  6. // 添加枚举对象的名称
  7. private final String name;
  8.  
  9. // 添加枚举对象的描述
  10. private final String desc;
  11.  
  12. private Season(String name,String desc){
  13. this.name = name;
  14. this.desc = desc;
  15. }
  16.  
  17. public String getName(){
  18. return name;
  19. }
  20.  
  21. public String getDesc(){
  22. return desc;
  23. }
  24. }

我们可以看到,有一个带参的私有构造函数,所以在定义枚举的时候可以直接赋值,而调用创建对象是由虚拟机自动完成的,还可以添加更多的属性,我们可以正常使用枚举对象。

  1. // 获取所有的枚举对象,返回的是数组
  2. Season[] values = Season.values();
  3. for (Season season : values) {
  4. System.out.println(season.getName() + " : " + season.getDesc());
  5. }
  6.  
  7. 春天 : 一年之计在于春
  8. 夏天 : 夏天好热 ~
  9. 秋天 : 秋水共长天一色
  10. 冬天 : 冬天好冷 ~

枚举类中实现抽象方法

这肯定有点迷糊,我们知道含有抽象方法的类是抽象类,那为什么枚举类不是 abstract 的也可以含有抽象方法呢 ?我们先来看看实现,待会说原因。

  1. enum Season{
  2.  
  3. SPRING("春天","一年之计在于春") {
  4. @Override
  5. public Season getNextSeason() {
  6. return Season.valueOf("SUMMER");
  7. }
  8. },SUMMER("夏天","夏天好热 ~ ") {
  9. @Override
  10. public Season getNextSeason() {
  11. return Season.valueOf("FALL");
  12. }
  13. },
  14. ... 省略
  15. ... 省略
  16. ... 省略
  17.  
  18. // 定义了一个抽象方法,获取下一个季节
  19. public abstract Season getNextSeason();
  20. }
  1.  

测试代码如下

  1. public static void main(String[] args) {
  2. String name = Season.SPRING.getNextSeason().getName();
  3. System.out.println(name); // 夏天
  4. }

是不是有种似懂非懂的感觉,没关系,我们来反编译看一看枚举类的内部构造你就会明白。

举个简单的例子来看一看枚举类的原理。就拿一个最简单的枚举来说明情况。

  1. public enum SeasonEnum {
  2. SPRING,SUMMER,FALL,WINTER;
  3. }

看一看反编译之后的代码,我使用的反编译工具是 jad 。

  1. public final class SeasonEnum extends Enum
  2. {
  3.  
  4. public static SeasonEnum[] values()
  5. {
  6. return (SeasonEnum[])$VALUES.clone();
  7. }
  8.  
  9. public static SeasonEnum valueOf(String s)
  10. {
  11. return (SeasonEnum)Enum.valueOf(SeasonEnum, s);
  12. }
  13.  
  14. private SeasonEnum(String s, int i)
  15. {
  16. super(s, i);
  17. }
  18.  
  19. public static final SeasonEnum SPRING;
  20. public static final SeasonEnum SUMMER;
  21. public static final SeasonEnum FALL;
  22. public static final SeasonEnum WINTER;
  23. private static final SeasonEnum $VALUES[];
  24.  
  25. static
  26. {
  27. SPRING = new SeasonEnum("SPRING", 0);
  28. SUMMER = new SeasonEnum("SUMMER", 1);
  29. FALL = new SeasonEnum("FALL", 2);
  30. WINTER = new SeasonEnum("WINTER", 3);
  31. $VALUES = (new SeasonEnum[] {
  32. SPRING, SUMMER, FALL, WINTER
  33. });
  34. }
  35. }

可以看到枚举类本质上就是一个继承了 Enum 的一个单例最终类,而我们定义的枚举对象也是在静态代码块中初始化了,同时我们也可以看到 values 方法的实现就是返回实例对象的数组,也就是枚举对象的数组,valueOf 方法接收一个字符串,返回的是字符串对应的枚举对象,若是找不到,会报错。

看到这我们也就能理解为什么我们可以在枚举类中定义抽象方法了,我们使用内部类实现了抽象方法,对应的每个对象在创建时都会实现相应的抽象方法。同样的道理,枚举类也可以实现接口,这里就不演示了。

说了这么多,也知道了枚举的好处,但是不得不说的是我在实际的项目中,枚举类的使用还真不多,下面就看看枚举类可以有哪些用处,以后有这种需求就可以考虑使用枚举来实现。

switch 语句支持枚举类型是从 JDK 1.5 才开始的,因为此时才有枚举这个特性。我们看一看具体的使用。

  1. /**
  2. * 服务器响应码
  3. */
  4. public enum ResponseCode {
  5.  
  6. SUCCESS(200,"访问成功"),FAIL(404,"页面不存在"),ERROR(500,"服务器内部错误");
  7.  
  8. private Integer num;
  9. private String desc;
  10.  
  11. private ResponseCode(Integer num,String desc){
  12. this.num = num;
  13. this.desc = desc;
  14. }
  15.  
  16. public Integer getNum() {
  17. return num;
  18. }
  19.  
  20. public String getDesc() {
  21. return desc;
  22. }
  23.  
  24. /*
  25. * 通过返回码得到枚举对象
  26. */
  27. public static ResponseCode getByNum(Integer num){
  28. for(ResponseCode code : values()){
  29. if(code.getNum().equals(num)){
  30. return code;
  31. }
  32. }
  33. return null;
  34. }
  35. }
  36. =============测试=====================
  37. public static void main(String[] args) {
  38. ResponseCode code = ResponseCode.getByNum(200);
  39. switch (code) {
  40. case SUCCESS:
  41. System.out.println("成功");
  42. break;
  43.  
  44. default:
  45. break;
  46. }
  47. }

在我做过的项目中,只有一处用到过枚举,用来记录字典的值,比方说,我写一个工具类,记录项目中使用到的所有字典相关数据。形如这样

  1. public class Keys {
  2. enum Sex{
  3. MALE,FEMALE;
  4. }
  5. enum State{
  6. SUCCESS,FAIL;
  7. }
  8. enum Month{
  9. }
  10. enum Week{
  11. }
  12.  
  13. public static void main(String[] args) {
  14. Keys.Sex.MALE.name();
  15. }
  16. }

但是在后面发现,还有更好用的配置字典的方式,创建一个字典类,将所有的字典数据放在一张表中,我们使用字典类来操作,这样要比上面使用枚举要好。

浅谈 Java 中的枚举的更多相关文章

  1. 浅谈java中的枚举类型(转)

    用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...

  2. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  3. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  4. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  5. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  6. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  7. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

  8. 浅谈Java中的final关键字

    浅谈Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  9. 【转】浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

随机推荐

  1. [转载]WebStorm快捷键操作

    http://www.cnblogs.com/yangjinjin/archive/2013/01/30/2883172.html 1. ctrl + shift + n: 打开工程中的文件,目的是打 ...

  2. Python核心编程——Chapter9

    好久没写过Python了,前一阵子忙这忙那的,都几乎把Python给丢掉了,话不多说,马上开始. 9.1.文件过滤.显示一个文件的所有行,并且忽略以井号开头的行. 其实这个题目比较基础,用shell语 ...

  3. petri网初步

    历史:Petri网的概念是德国的Carl Adam Petri早在1962年提出来的.他在他的论文里提出了一个新的信息流模型,这个模型基于系统各部分的异步并发的操作,并把各部分之间的关系用网状的图来描 ...

  4. Java NIO之拥抱Path和Files

    Java面试通关手册(Java学习指南)github地址(欢迎star和pull):https://github.com/Snailclimb/Java_Guide 历史回顾: Java NIO 概览 ...

  5. MyBatis 总结记录

    1.1MyBatis简介 MyBatis 是一个可以自定义SQL.存储过程和高级映射的持久层框架.MyBatis 摒除了大部分的JDBC代码.手工设置参数和结果集重获.MyBatis 只使用简单的XM ...

  6. REX系统了解1

    REX是高通开发出来的一个操作系统,起初它是为了在Inter 80186处理器上应用而开发的,到后来才转变成应用在ARM这种微处理器上.他历经了很多版本,代码也越来越多,功能也越来越完善.REX只用不 ...

  7. 关于分布式存储系统中-CAP原则(CAP定理)与BASE理论比较

    CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),三者不可得兼. CA ...

  8. jQuery-对标签元素 文本操作-属性操作-文档的操作

    一.对标签元素文本操作 1.1 对标签中内容的操作 // js var div1 = document.getElementById("div1"); div1.innerText ...

  9. 转载:Google 官方应用架构的最佳实践指南 赞👍

    官方给的实践指南,很有实际的指导意义,  特别是对一些小公司,小团队,给了很好的参考意义. 原文地址: https://developer.android.com/topic/libraries/ar ...

  10. python-windows下将单个py文件生成exe

    突然要生成一个exe给其他人用.紧急搜索下了 命令行参数获取用如下方法 from sys import argv base64path = argv[1] argv这个元组就是你的参数列表了,同C一样 ...