Enum类是java.lang包中一个类,他是Java语言中所有枚举类型的公共基类

定义

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable
  • 1

抽象类

  • 首先,抽象类不能被实例化,所以我们在java程序中不能使用new关键字来声明一个Enum,如果想要定义可以使用这样的语法:
enum enumName{value1,value2method1(){}method2(){}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 其次,看到抽象类,第一印象是肯定有类继承他。至少我们应该是可以继承他的,所以:
/*** @author hollis*/
public class testEnum extends Enum{
}
public class testEnum extends Enum<Enum<E>>{
}
public class testEnum<E> extends Enum<Enum<E>>{
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 尝试了以上三种方式之后,得出以下结论:Enum类无法被继承

  • 为什么一个抽象类不让继承?enum定义的枚举是怎么来的?难道不是对Enum的一种继承吗?带着这些疑问我们来反编译以下代码:

 enum Color {RED, BLUE, GREEN}
  • 1
  • 编译器将会把他转成如下内容:
/*** @author hollis*/
public final class Color extends Enum<Color> {public static final Color[] values() { return (Color[])$VALUES.clone(); }public static Color valueOf(String name) { ... }private Color(String s, int i) { super(s, i); }public static final Color RED;public static final Color BLUE;public static final Color GREEN;private static final Color $VALUES[];static {RED = new Color("RED", 0);BLUE = new Color("BLUE", 1);GREEN = new Color("GREEN", 2);$VALUES = (new Color[] { RED, BLUE, GREEN });}
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 短短的一行代码,被编译器处理过之后竟然变得这么多,看来,enmu关键字是java提供给我们的一个语法糖啊。。。从反编译之后的代码中,我们发现,编译器不让我们继承Enum,但是当我们使用enum关键字定义一个枚举的时候,他会帮我们在编译后默认继承java.lang.Enum类,而不像其他的类一样默认继承Object类。且采用enum声明后,该类会被编译器加上final声明,故该类是无法继承的。 PS:由于JVM类初始化是线程安全的,所以可以采用枚举类实现一个线程安全的单例模式

实现Comparable和Serializable接口

  • Enum实现了Serializable接口,可以序列化。 Enum实现了Comparable接口,可以进行比较,默认情况下,只有同类型的enum才进行比较(原因见后文),要实现不同类型的enum之间的比较,只能复写compareTo方法

泛型 “<”E extends Enum”<”E>>

  • 怎么理解 “<”E extends Enum”<”E>>

首先,这样写只是为了让Java的API更有弹性,他主要是限定形态参数实例化的对象,故要求只能是Enum,这样才能对 compareTo 之类的方法所传入的参数进行形态检查。所以,我们完全可以不必去关心他为什么这么设计

  • 首先我们先来“翻译”一下这个Enum

/*** @author hollis*/
enum Color{RED,GREEN,YELLOW
}
enum Season{SPRING,SUMMER,WINTER
}
public class EnumTest{public static void main(String[] args) {System.out.println(Color.RED.ordinal());System.out.println(Season.SPRING.ordinal());}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 代码中两处输出内容都是 0 ,因为枚举类型的默认的序号都是从零开始的

  • 要理解这个问题,首先我们来看一个Enum类中的方法(暂时忽略其他成员变量和方法):

/*** @author hollis*/
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {private final int ordinal;public final int compareTo(E o) {Enum other = (Enum)o;Enum self = this;if (self.getClass() != other.getClass() && // optimizationself.getDeclaringClass() != other.getDeclaringClass())throw new ClassCastException();return self.ordinal - other.ordinal;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 首先我们认为Enum的定义中没有使用Enum
public final int compareTo(Object o) 
  • 1
  • 当我们调用compareTo方法的时候依然传入两个枚举类型,在compareTo方法的实现中,比较两个枚举的过程是先将参数转化成Enum类型,然后再比较他们的序号是否相等。那么我们这样比较:
Color.RED.compareTo(Color.RED);
Color.RED.compareTo(Season.SPRING);
  • 1
  • 2
  • 如果在compareTo方法中不做任何处理的话,那么以上这段代码返回内容将都是true(因为Season.SPRING的序号和Color.RED的序号都是 0 )。但是,很明显, Color.RED和Season.SPRING并不相等

  • 但是Java使用Enum

The method compareTo(Color) in the type Enum<Color> is not applicable for the arguments (Season)
  • 1
  • 他说明,compareTo方法只接受Enum类型

  • Java为了限定形态参数实例化的对象,故要求只能是Enum,这样才能对 compareTo之类的方法所传入的参数进行形态检查。 因为“红色”只有和“绿色”比较才有意义,用“红色”和“春天”比较毫无意义,所以,Java用这种方式一劳永逸的保证像compareTo这样的方法可以正常的使用而不用考虑类型

PS:在Java中,其实也可以实现“红色”和“春天”比较,因为Enum实现了Comparable接口,可以重写compareTo方法来实现不同的enum之间的比较

成员变量

  • 在Enum中,有两个成员变量,一个是名字(name),一个是序号(ordinal)。 序号是一个枚举常量,表示在枚举中的位置,从0开始,依次递增
/*** @author hollis*/
private final String name;
public final String name() {return name;
}
private final int ordinal;
public final int ordinal() {return ordinal;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

构造函数

  • 前面我们说过,Enum是一个抽象类,不能被实例化,但是他也有构造函数,从前面我们反编译出来的代码中,我们也发现了Enum的构造函数,在Enum中只有一个保护类型的构造函数:
protected Enum(String name, int ordinal) {this.name = name;this.ordinal = ordinal;
}
  • 1
  • 2
  • 3
  • 4
  • 文章开头反编译的代码中private Color(String s, int i) { super(s, i); }中的super(s, i);就是调用Enum中的这个保护类型的构造函数来初始化name和ordinal

其他方法

  • Enum当中有以下这么几个常用方法,调用方式就是使用Color.RED.methodName(params…)的方式调用
public String toString() {return name;
}public final boolean equals(Object other) {return this==other;
}public final int hashCode() {return super.hashCode();
}public final int compareTo(E o) {Enum other = (Enum)o;Enum self = this;if (self.getClass() != other.getClass() && // optimizationself.getDeclaringClass() != other.getDeclaringClass())throw new ClassCastException();return self.ordinal - other.ordinal;
}public final Class<E> getDeclaringClass() {Class clazz = getClass();Class zuper = clazz.getSuperclass();return (zuper == Enum.class) ? clazz : zuper;
}public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name) {T result = enumType.enumConstantDirectory().get(name);if (result != null)return result;if (name == null)throw new NullPointerException("Name is null");throw new IllegalArgumentException("No enum constant " + enumType.getCanonicalName() + "." + name);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

参考资料

  • Java 7 源码学习系列(二)——Enum

from:https://blog.csdn.net/qiuchengjia/article/details/52910948

Java源码分析--Enum相关推荐

  1. 【Java源码分析】Java8的HashMap源码分析

    Java8中的HashMap源码分析 源码分析 HashMap的定义 字段属性 构造函数 hash函数 comparableClassFor,compareComparables函数 tableSiz ...

  2. 【Java源码分析】LinkedHashSet和HashSet源码分析

    类的定义 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, ...

  3. java 源码分析_Java 源代码编译成 Class 文件的过程分析

    原标题:Java 源代码编译成 Class 文件的过程分析 在上篇文章< Java三种编译方式:前端编译 JIT编译 AOT编译 >中了解到了它们各有什么优点和缺点,以及前端编译+JIT编 ...

  4. Java源码分析之HashMap(JDK1.8)

    一.HashMap概述 HashMap是常用的Java集合之一,是基于哈希表的Map接口的实现.与HashTable主要区别为不支持同步和允许null作为key和value.由于HashMap不是线程 ...

  5. 坦克大战java源码分析(上)

    坦克大战源码分析 一.mytank07.java文件分析 注:至上而下将不懂的语句.结构体含义.代码作用等作出解释: 1.包的使用 package com.haiding.tank_7; 包语句的语法 ...

  6. 【Java源码分析】Java8的ArrayList源码分析

    Java8的ArrayList源码分析 源码分析 ArrayList类的定义 字段属性 构造函数 trimToSize()函数 Capacity容量相关的函数,比如扩容 List大小和是否为空 con ...

  7. python打蛇_hprose for java源码分析-1 初识

    1.1初识 hprose是个开源RPC框架.支持语言 JAVA, C#,C++,Python,PHP等一系列语言.这里着重分析下hprose for java源码. 可以到https://github ...

  8. Java源码分析 AbstractList的迭代器实现(Itr和ListItr)

    Itr和ListItr的简介 AbstractList的有两个内部类实现了迭代器,一个内部类Itr实现了Iterator接口,一个内部类ListItr实现了ListIterator接口,后者其实就是前 ...

  9. java源码分析之ArrayList

    ArrayList就是传说中的动态数组,就是Array的复杂版本,它提供了如下一些好处:动态的增加和减少元素.灵活的设置数组的大小...... 认真阅读本文,我相信一定会对你有帮助.比如为什么Arra ...

最新文章

  1. 学习org-mode
  2. Google MapReduce
  3. 二分查找树性能分析(Binary Search Tree Performance Analysis)
  4. springboo整合security——权限设置
  5. (译文)在Ubuntu 14.04上成功运行ModelSim-Altera Starter Edition 10.1d
  6. 关于在n-1的数组中找到那个被减去的数及异或与位与
  7. win8超极本盘符误删找回数据的办法
  8. (24)css3盒子阴影
  9. 《编码规范和测试方法——C/C++版》作业 ·005——设计一组员工类
  10. pb 数据窗口插入数据_46MB 变4.5PB 数据炸弹:新方法突破性压缩资料
  11. 【路径规划】基于matlab人工势场法机器人自动避障【含Matlab源码 620期】
  12. 搞Java的年薪 40W 是什么水平? 1
  13. Handler sync barrier(同步屏障)
  14. 高3米直径10的半圆形求面积是多少
  15. nginx 通过路径分发 网站/端口/服务
  16. 企业物流营销组合模式探讨 (zt)
  17. 通过修改rom包永久获取root权限和所有应用调试功能ro.debuggable
  18. 「聚变」前端 客户端,第十七届 D2 终端技术大会来了!
  19. python selenium 元素定位和页面操作
  20. Anylogic轨道库入门

热门文章

  1. jboss7 加载module过程
  2. 数模学习笔记——粒子群
  3. 效率达CPU一万倍、内含800万神经元:英特尔发布神经形态芯片超算
  4. 老夫疗法少年狂:微软中国CTO黎江:不要给区块链贴标签,也不要非黑即白区分谁是好人谁是坏人
  5. 微信8年,干掉了短信也杀死了媒体?
  6. 灰度图像--图像增强 平滑之均值滤波、高斯滤波
  7. @autowired注入mapper_Intellij IDEA中Mybatis Mapper自动注入警告的6种解决方案
  8. 信息提醒之对话框(AlertDialog + ProgressDialog)-更新中
  9. 北京计算机工业学校96届,刘驰_北京理工大学计算机学院
  10. 复习笔记(三)——C++类和对象