1.在没有枚举之前,我们如果需要一些常量,比如说,我们想用一些常量来代替订单的几种状态,如已下单未付款、已付款未发货、已发货未确认收货、已收货未评价、已评价。我们会定义一个用来装常量的类,比如:

package com.xdx.learn;

public class OrderConstant {
public static final int UNPAY=1;//未付款
public static final int UNDELIVER=2;//未发货
public static final int UNRECEIVE=3;//未收货
public static final int UNCOMMENT=4;//未评价 }

  在其他地方调用的时候,我们直接通过OrderConstant .UNPAY就可以获取到这个常量。

  2.有了枚举类型以后,我们会这样来写代码。

  新建一个枚举类。

  

public enum OrderEnum {
UNPAY("unpay",1),UNDELIVER("undeliver",2),UNRECEIVE("unreceive",3),UNCOMMENT("uncomment",4);
private String key;
private int value;
private OrderEnum(String key,int value){
this.key=key;
this.value=value;
} public String getKey() {
return key;
} public void setKey(String key) {
this.key = key;
} public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
} public static void main(String args[]){
System.out.println(OrderEnum.UNPAY.getKey());
System.out.println(OrderEnum.UNPAY.getValue());
} }

  上面就是一个枚举类,它有如下特点。

  (1)它不用class修饰,而是用enum关键字来修饰。但是要知道的是,它本质上还是一个类。

  (2)它的构造函数不能用public修饰,只能用private来修饰,也就是说,我们不能在外部实例化一个枚举类的对象。这让你想到了什么呢?是不是单例模式。

  (3)UNPAY("unpay",1),UNDELIVER("undeliver",2),UNRECEIVE("unreceive",3),UNCOMMENT("uncomment",4);这几个都是该枚举类的对象(他们都是OrderEnum类型的),以静态常量的成员变量的形式存在于枚举类中。事实上,他们是public static final类型的,所以我们可以在类外部使用类名.成员变量,比如OrderEnum.UNPAY的形式来访问。

  (4)一旦你定义了一个枚举类,则必须也将它的实例创建出来,即是上述的UNPAY("unpay",1)这些实例。实例的创建被简化了,只需要调用构造函数,不需要用new关键字。

  其实,按照我的理解,上述的枚举类可以用以下的类来代替。

  

package com.xdx.learn;

public class OrderMulti {
private String key;
private int value;
private OrderMulti(String key,int value){
this.key=key;
this.value=value;
} public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
} public static final OrderMulti UNPAY=new OrderMulti("unpay", 1);
public static final OrderMulti UNDELIVER=new OrderMulti("undeliver", 2);
public static final OrderMulti UNRECEIVE=new OrderMulti("unreceive", 3);
public static final OrderMulti UNCOMMENT=new OrderMulti("uncomment", 4);
public static void main(String args[]){
System.out.println(OrderMulti.UNPAY.getKey());
System.out.println(OrderMulti.UNPAY.getValue());
} }

  没错,枚举类就相当于一个带有多例(多例模式)的java类。只不过java的语法帮我们做了这些显式实例化的操作,并且以一种比较简单的语法来表示。就变成了enum了。

  3.再深入一点,其实枚举类都是Enum类的子类,去查jdk源码,发现Enum是一个抽象的泛型类,其定义为public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable。事实上,上述的OrderEnum类,可以理解成这样的一个类。

  public class OrderEnum extends Enum<OrderEnum>,没错,泛型的类型实参就是这个枚举类本身。

  不过当你真的在eclipse里面敲入上面的一个类,会发现报错,因为Enum这个类是不可继承的,提示的错误是The type OrderEnum may not subclass Enum<A> explicitly。不能显式的继承Enum。jdk在编译阶段就拒绝了一个类去继承Enum,具体什么原因,怎么实现,我也不知道。我们只需要知道enum修饰的类,它的父类是Enum就行了。

  既然如此,enum修饰的类也就不可以在继承其他的类了,因为java是单继承的。当然可以通过实现接口的方式去对enum类进行扩展。

  由于枚举类继承自Enum,那么Enum里面的一些方法他也可以用。看如下代码,使用了几个比较常用的方法。

  

    public static void main(String args[]){
System.out.println(OrderEnum.UNPAY.getKey());
System.out.println(OrderEnum.UNPAY.getValue());
//name()方法获取该枚举类实例的名称
System.out.println(OrderEnum.UNPAY.name());
//ordinal()方法获取该枚举类实例在所有实例中的排序,从0开始。
System.out.println(OrderEnum.UNPAY.ordinal());
//compareTo()方法比较两个枚举实例的排序,可认为是前者的ordinal-后者的ordinal的值。
System.out.println(OrderEnum.UNPAY.compareTo(OrderEnum.UNDELIVER));
System.out.println(OrderEnum.UNRECEIVE.compareTo(OrderEnum.UNDELIVER));
System.out.println(OrderEnum.UNCOMMENT.compareTo(OrderEnum.UNDELIVER));
//获取该枚举对象的类
System.out.println(OrderEnum.UNPAY.getDeclaringClass());
//验证枚举类的父类确实是Enum
System.out.println(OrderEnum.UNPAY.getDeclaringClass().getSuperclass());
System.out.println(OrderEnum.UNPAY.equals(OrderEnum.UNCOMMENT));
//遍历枚举类中实例
for(OrderEnum orderenum:OrderEnum.values()){
System.out.println(orderenum.getKey());
}
}

  上述代码的运行结果为:

  unpay
  1
  UNPAY
  0
  -1
  1
  2
  class com.xdx.learn.OrderEnum
  class java.lang.Enum
  false
  unpay
  undeliver

  unreceive
  uncomment

  4.只要将枚举理解成一个实现了多例模式的类,运用起来就不会有什么困难。但是也有人会问,我用第一种方式,即直接使用一个public static final int UNPAY=1。这样的常量。不是也可以实现枚举需要的功能吗?为何还大费周章去定义一个枚举类呢?我觉得是基于如下几方面考虑的。

  (1)首先枚举类的类名可以有一定的指示作用,比如我们给一个枚举类命名为week,我们可以知道它应该就是代表星期,而在枚举之前,我们使用常量的容器类,往往只定义一个类,命名为类似于Constant这样的类,要去里面找寻其中的常量值是比较费劲的。

  (2)当用枚举作为函数的形参的时候,能起到限定的作用。比如我有一个函数 ,我可以定义为void func(int x),接受一些常量值。我也可以定义成void func(OrderEnum orderEnum)这样的形式。后者比前者的优点在于它限制了传入的参数只能是该枚举类的实例,而前者则可以传入任意整型。

  

java枚举细节的更多相关文章

  1. Java 枚举用法详解

    概念 enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性. 在Java中,被 enum 关键字修饰的类型就是枚举类型.形式如下: enum Color { RED, GR ...

  2. 【转】Java 枚举7常见种用法

    原文网址:http://softbeta.iteye.com/blog/1185573 Java 枚举7常见种用法 博客分类: java java枚举enmu  原创地址:http://blog.li ...

  3. Java枚举类使用

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

  4. Java 枚举(enum) 详解7种常见的用法

    Java 枚举(enum) 详解7种常见的用法 来源 https://blog.csdn.net/qq_27093465/article/details/52180865 JDK1.5引入了新的类型— ...

  5. 【转载】Java枚举类型的使用

    枚举类型概念 package com.lxq.enumm; public class EnumDemoOne { private enum InnerEnum { RED, GREEN, YELLOW ...

  6. Java 枚举常见7种用法

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

  7. java枚举中常见的7中用法

    2016年08月11日 11:14:45 李学凯  原文链接https://blog.csdn.net/qq_27093465/article/details/52180865 JDK1.5引入了新的 ...

  8. java枚举怎么用的

    package com.pingan.property.icore.pap.common.constants; /** * */public enum UMAuthStatusEnum impleme ...

  9. Java提高篇(三五)-----Java集合细节(一):请为集合指定初始容量

    集合是我们在Java编程中使用非常广泛的,它就像大海,海纳百川,像万能容器,盛装万物,而且这个大海,万能容器还可以无限变大(如果条件允许).当这个海.容器的量变得非常大的时候,它的初始容量就会显得很重 ...

随机推荐

  1. Maven2的配置文件settings.xml

    简介: 概览 当Maven运行过程中的各种配置,例如pom.xml,不想绑定到一个固定的project或者要分配给用户时,我们使用settings.xml中的settings元素来确定这些配置.这包含 ...

  2. 我是如何理解Android的Handler模型_2

    对比例程说明,如: 例:在新新线程中替换TextView显示内容. 界面如下,单击按键后original data 替换为 changed data Handler Message部分实现步骤: 1. ...

  3. 记录一次Session偶尔获取不到的解决过程

    导读 平台下某子系统有密码登录需求,初步考虑用Session,登录后设置Session[key]=value;Session中若某key对应的Session,即Session[key]为null则限制 ...

  4. 安装scrapy框架的常见问题及其解决方法

    下面小编讲一下自己在windows10安装及配置Scrapy中遇到的一些坑及其解决的方法,现在总结如下,希望对大家有所帮助. 常见问题一:pip版本需要升级 如果你的pip版本比较老,可能在安装的过程 ...

  5. c++/cmake /Android NDK 动态链接库交叉编译笔记

    项目使用cmake管理,由于项目的需要,核心代码要求跨 Linux/Windows/Android 三平台.Windows和Linux都好说,但Android NDK费了一番功夫还是没有解决.临时的解 ...

  6. 在PHP中,将一个汉字数组按照拼音首字母进行排序

    (之前发的这篇博文因为含有敏感关键字,只好重发一遍了) <?php $str = "我们可以在浏览器中看到,当鼠标移到元素上时,元素开始向右移动,开始比较慢,之后则比较快,移开时按原曲 ...

  7. PHP制作API接口

    需要单一入口文件,可以使用autoload来加载 <?php //获取get参数 $m = !empty($_GET['m'])?$_GET['m']:'Index'; $a = !empty( ...

  8. python - dict.setdefault

    index = dict.serdefault(key,default) 尝试往dict中插入新键值key,如果key已存在就原dict不变,否则插入key:defalut:返回值为key在dict中 ...

  9. 关于mysql插入数据异常

    今天创建数据库时,在插入数据时出现了几个问题.(首次在LInux环境下创建数据库) 一个是关于SQL Error [1146] [42S02]: Table 'struts2exec.s_user' ...

  10. IntelliJ IDEA(二) :面板介绍

    一.面板说明 IDEA面板的全貌如下图 二.菜单栏 下面会简单介绍下一些常用的部分菜单使用,如有疑问或补充欢迎留言. (1).File文件 1. New:新建一个工程 可以新建project,导入已存 ...