1、反遍Yi枚举类
1.1 举例1:普通枚举类
enum代码:
public enum ColorEnum {
RED,
BLACK,
BLUE;
ColorEnum() {
}
}
编Yi并反编Yi:
反编Yi后的代码:
多了values(),valueOf(String s)方法
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: ColorEnum.java
//final类,不能被继承;继承了抽象类Enum,不能再继承别的类
public final class ColorEnum extends Enum
{
//得到枚举常量集合
public static ColorEnum[] values()
{
return (ColorEnum[])$VALUES.clone();
}
//根据s得到对Ying的枚举常量
public static ColorEnum valueOf(String s)
{
return (ColorEnum)Enum.valueOf(ColorEnum, s);
}
//私You的构造函数
private ColorEnum(String s, int i)
{
super(s, i);
}
//枚举常量被解析成static final属性
public static final ColorEnum RED;
public static final ColorEnum BLACK;
public static final ColorEnum BLUE;
private static final ColorEnum $VALUES[];
//静态代码块:在clinit方法执行的时候,执行
static
{
RED = new ColorEnum("RED", 0);
BLACK = new ColorEnum("BLACK", 1);
BLUE = new ColorEnum("BLUE", 2);
$VALUES = (new ColorEnum[] {
RED, BLACK, BLUE
});
}
}
1.2 举例1:带 属性的 枚举类
枚举类除了能带属性外,还能带方法等,和普通类类似。
enum代码:
public enum OperateEnum {
ADD("add", 1),
SUBTRACT("subtract", 2),
MULTIPLY("multiply", 3),
DIVIDE("divide", 4);
private String name;
private int index;
OperateEnum(String name, int index) {
this.name = name;
this.index = index;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
编Yi并反编Yi:
反编Yi后的代码:
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: OperateEnum.java
//final类,不能被继承;该类继承自抽象类Enum,不能在继承别的类
public final class OperateEnum extends Enum
{
//得到枚举值集合
public static OperateEnum[] values()
{
return (OperateEnum[])$VALUES.clone();
}
//根据s找到对Ying的枚举值
public static OperateEnum valueOf(String s)
{
return (OperateEnum)Enum.valueOf(OperateEnum, s);
}
//私You的构造函数
private OperateEnum(String s, int i, String s1, int j)
{
super(s, i);
name = s1;
index = j;
}
public String getName()
{
return name;
}
public void setName(String s)
{
name = s;
}
public int getIndex()
{
return index;
}
public void setIndex(int i)
{
index = i;
}
//static final类型
public static final OperateEnum ADD;
public static final OperateEnum SUBTRACT;
public static final OperateEnum MULTIPLY;
public static final OperateEnum DIVIDE;
private String name;
private int index;
private static final OperateEnum $VALUES[];
//静态代码块,在类执行clinit的时候,执行
static
{
ADD = new OperateEnum("ADD", 0, "add", 1);
SUBTRACT = new OperateEnum("SUBTRACT", 1, "subtract", 2);
MULTIPLY = new OperateEnum("MULTIPLY", 2, "multiply", 3);
DIVIDE = new OperateEnum("DIVIDE", 3, "divide", 4);
$VALUES = (new OperateEnum[] {
ADD, SUBTRACT, MULTIPLY, DIVIDE
});
}
}
枚举类和普通类的区别:
- 如果有构造器,必须用private修饰
- 枚举类不能派生子类
- 枚举类所有的实例必须在第一行显示定义。系统会自动给这些实例加上public static final修饰,无须程序员显示定义
- 枚举类默认提供了values()方法,方便遍历所有的枚举值
2、抽象类Enum
Enum类结构
enum中的方法(Enum提供的方法)
- public final int compareTo(E o) 比较相同类型的枚举值ordinal
- public final int ordinal() 返回枚举的索引值,第一个枚举值从零开始
- public final String name() 返回枚举实例名称
- public String toString() 返回枚举常量名称
- valueOf(String)
- getDeclaringClass() 返回与此枚举常量对应的Class对象枚举类型
- equals(Object other) other==this的时候,才返回true
- clone() 和 readObject()(YongYu反序列化):这2个方法均抛出Yi常,从而保证不能生成新的实例,保证了真正的单例
open jdk 1.8
package java.lang;
import java.io.Serializable;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
//这是所有Java语言枚举类型的公共基类
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
/**
*此枚举常量的名称,如枚举声明中声明的那样。
*大多数程序员应该使用{@link #toString}方法而不是
*访问此字段。
*/
private final String name;
/**
*返回此枚举常量的名称,与其中声明的完全相同
*枚举声明。
*
* <b>大多数程序员应该使用{@link #toString}方法
*优先于此,因为toString方法可能会返回
*更友好的用户名。</ b>此方法主要用于
*在特殊情况下使用,正确性取决于获得
*确切名称,不会因版本而异。
*
* @return此枚举常量的名称
*/
public final String name() {
return name;
}
/**
*此枚举常数的序数(其位置
*在枚举声明中,分配初始常量
*序数为零)。
*
*大多数程序员对此字段没有用处。 它是专门设计的
*供复杂的基于枚举的数据结构使用,例如
* {@link java.util.EnumSet}和{@link java.util.EnumMap}。
*/
private final int ordinal;
/**
*返回此枚举常量的序数(其位置
*在其枚举声明中,其中分配了初始常量
*序数为零)。
*
*大多数程序员都没有使用此方法。 它是
*设计用于复杂的基于枚举的数据结构,例如
*作为{@link java.util.EnumSet}和{@link java.util.EnumMap}。
*
* @return此枚举常量的序数
*/
public final int ordinal() {
return ordinal;
}
/**
*唯一的构造函数。 程序员无法调用此构造函数。
*它由编译器响应的代码使用
*枚举类型声明。
*
* @param name - 此枚举常量的名称,即标识符
*用于申报。
* @param ordinal - 此枚举常量的序数(其位置
*在枚举声明中,分配初始常量
*序数为零)。
*/
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
/**
* @return此枚举常量的名称
*/
public String toString() {
return name;
}
public final boolean equals(Object other) {
return this==other;
}
/**
* Returns a hash code for this enum constant.
*
* @return a hash code for this enum constant.
*/
public final int hashCode() {
return super.hashCode();
}
/**
*抛出CloneNotSupportedException。 这保证了枚举
*永远不会被克隆,这是保持“单例”所必需的
* 状态。
*
* @return(永不返回)
*/
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/**
* Compares this enum with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
*
* Enum constants are only comparable to other enum constants of the
* same enum type. The natural order implemented by this
* method is the order in which the constants are declared.
*/
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
/**
* @return与此枚举常量对应的Class对象枚举类型
*/
@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)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);
}
/**
* enum classes cannot have finalize methods.
*/
protected final void finalize() { }
/**
* 防止默认的反序列化,so,反序列化的时候,不能生成新的实例,保证了真正的单例
*/
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
throw new InvalidObjectException("can't deserialize enum");
}
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("can't deserialize enum");
}
}
3、总结
枚举本质上是通过普通的类来实现的,只是编译器为我们进行了处理。每个枚举类型都继承自 java.lang.Enum,并自动添加了 values 和 valueOf 方法。而每个枚举常量是一个静态常量字段,使用内部类实现,该内部类继承了枚举类。所有枚举常量都通过静态代码块来进行初始化,即在类加载期间就初始化。另外通过把 clone、readObject、writeObject 这三个方法定义为 final 的,同时实现是抛出相应的异常。这样保证了每个枚举类型及枚举常量都是不可变的。可以利用枚举的这两个特性来实现线程安全的单例。
参考
https://blog.csdn.net/niuzhucedenglu/article/details/79540799