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. js贪吃蛇-简单版

    分享个用原生js写的贪吃蛇,最近在学java,按照当年写的 js的思路,转换成java,换汤不换药 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...

  2. Docker安装和卸载

    一:卸载旧版本 老版本的Docker被称为docker或docker-engine.如果安装了这些,请卸载它们以及相关的依赖项. $ sudo yum remove docker \ docker-c ...

  3. [转载] HBase vs Cassandra:我们迁移系统的原因

    转载自http://www.csdn.net/article/2010-11-29/282698 我的团队近来正在忙于一个全新的产品——即将发布的网络游戏www.FightMyMonster.com. ...

  4. 学会WCF之试错法——安全配置报错分析

    安全配置报错分析 服务端配置 <system.serviceModel> <bindings> <wsHttpBinding> <binding name = ...

  5. MXNet之ps-lite及parameter server原理

    MXNet之ps-lite及parameter server原理 ps-lite框架是DMLC组自行实现的parameter server通信框架,是DMLC其他项目的核心,例如其深度学习框架MXNE ...

  6. thinphp原生异步分页

    异步分页: $sql="............";   $result=$m->query($sql);   $count =count($result);   $page ...

  7. P3092 [USACO13NOV]没有找零No Change

    题目描述 Farmer John is at the market to purchase supplies for his farm. He has in his pocket K coins (1 ...

  8. A workaround to change shared memory size for Docker containers in AWS ECS

    Issue Because of not supporting to specify the following docker run parameter, containers in ECS can ...

  9. java 之 建造者模式(大话设计模式)

    建造者模式,在笔者看来比较试用于,定制一个业务流程,而流程的细节又不尽相同,每个细节又必不可少,这时应考虑使用建造者模式. 大话设计模式-类图 先看下笔者写的一个简单的例子. /** * 所有建造过程 ...

  10. 理解OC“属性”这一概念

    1.定义一个属性,编译器会自动编写相关的存取方法和实例变量,如果不想使用系统默认的实例变量,可以使用@synthesize(合成)语法来指实例变量的名字,如果不想编译器自动合成存取方法,则可以自己实现 ...