Java枚举类使用场景及实例解析

 更新时间:2020年04月07日 09:37:11   作者:Chsoul''S Blog  
这篇文章主要介绍了Java枚举类使用场景及实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

为什么要用枚举类

什么场景会用到枚举,比如在表示一周的某一天,一年中的四季,这样一组常量的时候我们会用到枚举。在Java引入枚举类之前常用一组int常量来表示枚举,这种方式称为int枚举模式(int enum pattern)。

private static final int MONDAY = 1;
private static final int TUESDAY = 2;
private static final int WEDNESDAY = 3;
private static final int THURSDAY = 4;

private static final int CODE_START = 1;
private static final int CODE_STATUS = 2;
private static final int CODE_STOP = 3;

这种我们非常习惯的模式其实存在着很多不足和问题,

  • int枚举组不具备命名空间的能力,当表示具有相同命名常量时,需要添加前缀避免冲突
  • int表示的枚举值不具有描述性,需要遍历判断具体的值并添加描述
  • int枚举模式不具有安全性,此外int类型是编译时常量,如果与int枚举常量关联的值发生变化,必须重新编译,不重新编译虽然不影响运行,但是准确性已经不能保证

即便是升级为用String来表示枚举值,String枚举模式(String enum pattern),但这样同样存在其他问题,

初学者容易直接把字符串常量硬编码到代码中,不使用对应的常量字段(filed)名,一旦书写错误,编译器无法检查,但在运行时会报出异常

String枚举模式会存在一定的性能问题,涉及到字符串的比较操作

因此Java引入了枚举类型解决int和String枚举模式带来的诸多不足,枚举类型保证了编译时的类型安全,枚举类型有自己独立的命名空间,枚举类型便于扩展,可以添加方法和域实现其他的外部接口。

如何使用枚举类

创建枚举类

Java中枚举是一种特殊的引用类型,是类(Class)的一种,JDK1.5中开始引入枚举类型,在Java中使用enum关键字来声明枚举类,枚举类编译后默认继承了java.lang.Enum,因此枚举类不能在继承其他类,枚举一般用来声明某一特定类型的有穷集合,如用枚举表示四季

public enum Season {
  SPRING,SUMMER,FALL,WINTER
}

枚举类API

参考JDK api 1.8.CHM,可以看到枚举类的常用api如下:

name public final String name()

返回此枚举常量的名称,与其枚举声明中声明的完全相同。 大多数程序员应该使用toString()方法,因为toString方法可能会返回一个更加用户友好的名称。 该方法主要用于专门的情况,其中正确性取决于获得确切的名称,这从发布到发布不会有所不同。

ordinal public final int ordinal()

返回此枚举常数的序数(其枚举声明中的位置,其中初始常数的序数为零)。 大多数程序员将不会使用这种方法。 它被设计为使用复杂的基于枚举的数据结构,如EnumSet和EnumMap 。

toString public String toString()

返回声明中包含的此枚举常量的名称。 该方法可以被覆盖,尽管它通常不是必需或不可取的。 当一个更“程序员友好”的字符串形式存在时,枚举类型应该覆盖此方法。

重写: toString 在 Object

compareTo public final int compareTo(E o)

将此枚举与指定的对象进行比较以进行订购。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。 枚举常数仅与相同枚举类型的其他枚举常量相当。 该方法实现的自然顺序是声明常量的顺序。

Specified by: compareTo 在界面Comparable<E extends Enum<E>

参数 :o - 要比较的对象。

结果 :负整数,零或正整数,因为该对象小于,等于或大于指定对象。

getDeclaringClass public final Class<E> getDeclaringClass()

返回与此枚举常量的枚举类型相对应的Class对象。 当且仅当e1.getDeclaringClass()== e2.getDeclaringClass())时,两个枚举常量e1和e2具有相同的枚举类型。 (此方法返回的值可能与使用常量特定类体的枚举常数Object.getClass()方法返回的值不同)

结果:该类对象对应于此枚举常量的枚举类型

valueOf public static <T extends Enum<T>> T valueOf(Class <T> enumType,String name)

返回具有指定名称的指定枚举类型的枚举常量。 该名称必须与用于声明此类型的枚举常量的标识符完全一致。 (不允许使用外来空白字符。)
请注意,对于特定枚举类型T ,可以使用该枚举上隐式声明的public static T valueOf(String)方法,而不是使用此方法将名称映射到

相应的枚举常量。 枚举类型的所有常量可以通过调用该类型的隐式public static T[] values()方法来获得。

values

此方法并未在API中提供,返回枚举类型所有对象实例,返回值枚举类型的数组。

枚举应用案例

上面简单描述了如何声明一个枚举类,这里结合实际应用场景描述枚举的其他用法

单例设计模式

说到单例模式很多人会比较熟悉懒汉、饿汉等常见的单例书写模式,用枚举表示枚举还是比较少见的,对于单例设计模式的多种写法,单元素的枚举类型已经成为实现Singleton的最佳方法。首先回顾下单例设计模式要求满足的特点:

  • 构造方法私有化;
  • 实例化的变量引用私有化;
  • 获取实例的方法共有。
public enum Singleton {
  INSTANCE;
  public Singleton getInstance(){
    return INSTANCE;
  }
}

使用枚举方式创建单例的好处:

  • 避免反射攻击
  • 避免序列化问题

有穷对象集合

枚举类型中的构造器默认私有化,只能添加private修饰或者不添加

枚举类型中定义的抽象方法必须被所有常量中的具体方法所覆盖,特定于常量的方法实现可以结合特定于常量的数据结合起来

用枚举表示加减乘除的操作

public enum Operation {
  PLUS("+","加法"){
    public double apply(double x,double y){
      return x + y;
    }
  },
  MINUS("-","减法"){
    public double apply(double x,double y){
      return x - y;
    }
  },
  TIMES("*","乘法"){
    public double apply(double x,double y){
      return x * y;
    }
  },
  DIVIDE("/","除法"){
    public double apply(double x,double y){
      return x / y;
    }
  };

  private final String symbol;
  private final String operName;

  public String getSymbol() {
    return symbol;
  }
  public String getOperName() {
    return operName;
  }
  Operation(String symbol, String operName){
    this.symbol = symbol;
    this.operName = operName;
  }
  public abstract double apply(double x,double y);
}

调用枚举中的方法

public class TestOpera {
  public static void main(String[] args) {
    double x = 1;
    double y = 1;
    for(Operation operate : Operation.values()){
      System.out.println(
      operate.getOperName()+":"+x+operate.getSymbol()+y+" = "+operate.apply(x,y)
      );
    }
  }
}

输出结果

加法:1.0 + 1.0 = 2.0
减法:1.0 - 1.0 = 0.0
乘法:1.0 * 1.0 = 1.0
除法:1.0 / 1.0 = 1.0

引入枚举类型,不仅可以描述枚举本身,还可以添加描述性字符串,甚至给每个对象添加结合特有常量的行为,也不用考虑其他安全性为题。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java实现文件上传和下载的方法详解

    Java实现文件上传和下载的方法详解

    文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上。文件下载,也称为download,是指将文件从服务器传输到本地计算机的过程。本文将用Java实现文件上传和下载,需要的可以参考一下
    2022-09-09
  • Java初学者了解

    Java初学者了解"=="与equals的区别

    这篇文章主要介绍了Java初学者了解"=="与equals的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • IntelliJ IDEA配置java环境及解决IDEA不能直接运行单个JAVA文件的问题

    IntelliJ IDEA配置java环境及解决IDEA不能直接运行单个JAVA文件的问题

    这篇文章主要介绍了IntelliJ IDEA配置java环境及解决IDEA不能直接运行单个JAVA文件的问题,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • 关于spring的自定义缓存注解分析

    关于spring的自定义缓存注解分析

    这篇文章主要介绍了关于spring的自定义缓存注解分析,因为所有的key的失效时间都一样,要想实现不同的key不同的失效时间,就得需要自定义缓存注解,需要的朋友可以参考下
    2023-05-05
  • MyBatis如何处理MySQL字段类型date与datetime

    MyBatis如何处理MySQL字段类型date与datetime

    这篇文章主要介绍了MyBatis如何处理MySQL字段类型date与datetime问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • spring boot过滤器FilterRegistrationBean实现方式

    spring boot过滤器FilterRegistrationBean实现方式

    这篇文章主要介绍了spring boot过滤器FilterRegistrationBean实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • java DecimalFormat常用方法详解

    java DecimalFormat常用方法详解

    这篇文章主要为大家详细介绍了java DecimalFormat的常用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • 流读取导致StringBuilder.toString()乱码的问题及解决

    流读取导致StringBuilder.toString()乱码的问题及解决

    这篇文章主要介绍了流读取导致StringBuilder.toString()乱码的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Java实现AWT四大事件的详细过程

    Java实现AWT四大事件的详细过程

    AWT的事件处理是一种委派式事件处理方式:普通组件(事件源)将整个事件处理委托给特定的对象(事件监听器);当该事件源发生指定的事件时,就通知所委托的事件监听器,由事件监听器来处理这个事件
    2022-04-04
  • 基于Spring整合mybatis的mapper生成过程

    基于Spring整合mybatis的mapper生成过程

    这篇文章主要介绍了Spring整合mybatis的mapper生成过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03

最新评论