参考反编译那些事儿(二)—枚举的反编译
Java枚举类,你真的了解吗?
public enum ResultCode {
/** 有没有发现写枚举类的这一部分就像是在调用构造方法 */
SUCCESS(1, "成功"),
PARAM_IS_INVALID(10001, "参数无效"),
PARAM_IS_BLANK(10002, "参数为空"),
PARAM_TYPE_BIND_ERROR(10003, "参数类型错误"),
PARAM_NOT_COMPLETE(10004, "参数缺失"),
//上面的逗号可去可不去, 并不会导致编译错误
;
private Integer code;
private String message;
//构造函数默认并且必须是private
ResultCode(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer code() {
return this.code;
}
public String message() {
return this.message;
}
}
所有的枚举类在编译之后会自动继承enum类, 并且会自动生成一个values()方法
//只放出部分常见代码
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
/**
实例的名字, 类型为字符串
即ResultCode.SUCCESS为SUCCESS, ResultCode.PARAM_IS_INVALID为PARAM_IS_INVALID
*/
private final String name;
public final String name() {
return name;
}
/**
实例的索引, 从0开始
即ResultCode.SUCCESS.ordinal()为0, ResultCode.PARAM_IS_INVALID.ordinal()为1
*/
private final int ordinal;
public final int ordinal() {
return ordinal;
}
//toString方法与name()一样
public String toString() {
return name;
}
//判断两个枚举实例是否一样, 注意这里使用的是==, 直接比引用, 说明枚举类的实例是单例的
public final boolean equals(Object other) {
return this==other;
}
/**
比较两个枚举实例的索引详见, 返回的int
上面我们知道ResultCode.SUCCESS.ordinal()为0, ResultCode.PARAM_IS_INVALID.ordinal()为1
所以ResultCode.SUCCESS.compareTo(ResultCode.PARAM_IS_INVALID)为0-1=-1
*/
public final int compareTo(E o) {
//略去实现代码
}
}
验证:
//ResultCode.values()会返回ResultCode这个枚举类的所有实例, 类型为ResultCode[]
for (ResultCode resultCode : ResultCode.values()) {
System.out.println(resultCode.name());
System.out.println(resultCode.ordinal());
System.out.println(resultCode.compareTo(ResultCode.SUCCESS));
}
//ResultCode.valueOf()会返回name与参数相等的枚举实例
ResultCode SUCCESS = ResultCode.valueOf("SUCCESS");
System.out.println(SUCCESS.equals(ResultCode.SUCCESS)); //输出为true
/**
* 枚举类可以有抽象方法,但是必须在它的实例中实现
*/
public enum AbstractWeek {
MONDAY(0,"星期一") {
@Override
public AbstractWeek getNextDay() {
return TUESDAY;
}
}, TUESDAY(1,"星期二") {
@Override
public AbstractWeek getNextDay() {
return WEDNESDAY;
}
}, WEDNESDAY(2,"星期三") {
@Override
public AbstractWeek getNextDay() {
return THURSDAY;
}
}, THURSDAY(3,"星期四") {
@Override
public AbstractWeek getNextDay() {
return FRIDAY;
}
}, FRIDAY(4,"星期五") {
@Override
public AbstractWeek getNextDay() {
return SATURDAY;
}
}, SATURDAY(5,"星期六") {
@Override
public AbstractWeek getNextDay() {
return SUNDAY;
}
}, SUNDAY(6,"星期日") {
@Override
public AbstractWeek getNextDay() {
return MONDAY;
}
};
private int num;
private String desc;
AbstractWeek(int num,String desc) {
this.num = num;
this.desc=desc;
}
//一个抽象方法
public abstract AbstractWeek getNextDay();
}
public enum Weather {
Sunny(1, "晴天") {
@Override
public String test() {
return "今天阳光明媚!!!\n";
}
},
Rainy(2, "雨天") {
@Override
public String test() {
return "出门别忘带把雨伞哦!!!\n";
}
},
Cloudy(3, "多云") {
@Override
public String test() {
return "别出去登高望远了,你看不远的,呵呵呵!!!\n";
}
};
private int value;
private String label;
private Weather(int value, String label) {
this.value = value;
this.label = label;
}
public int getValue() {
return value;
}
public String getLabel() {
return label;
}
public abstract String test();
}
我们将上述代码进行反编译:
import java.io.PrintStream;
import java.util.*;
//枚举类继承了Enum, 所以我们在定义的时候不能再继承其他的类了
//非抽象枚举类默认是final的, 所以不要去继承非抽象的枚举类
public abstract class Weather extends Enum {
//这里s表示name, i表示ordinal
//构造函数为私有的
private Weather(String s, int i, int value, String label) {
super(s, i);
this.value = value;
this.label = label;
}
public int getValue() {
return value;
}
public String getLabel() {
return label;
}
//我们自己定义的抽象方法
public abstract String test();
//values()返回所有枚举类的实例
public static Weather[] values() {
Weather aweather[];
int i;
Weather aweather1[];
System.arraycopy(aweather = ENUM$VALUES, 0, aweather1 = new Weather[i = aweather.length], 0, i);
return aweather1;
}
public static Weather valueOf(String s) {
return (Weather) Enum.valueOf(Weather, s);
}
Weather(String s, int i, int j, String s1, Weather weather) {
this(s, i, j, s1);
}
//这是我们所定义的枚举类实例, 这也是为什么我们在定义枚举类的时候就像是在调用构造函数
//每一个变量都是public static final
public static final Weather Sunny;
public static final Weather Rainy;
public static final Weather Cloudy;
private int value;
private String label;
private static final Weather ENUM$VALUES[];
static {
Sunny = new Weather("Sunny", 0, 1, "\u6674\u5929") {
public String test() {
return "\u4ECA\u5929\u9633\u5149\u660E\u5A9A\uFF01\uFF01\uFF01\n";
}
};
Rainy = new Weather("Rainy", 1, 2, "\u96E8\u5929") {
public String test() {
return "\u51FA\u95E8\u522B\u5FD8\u5E26\u628A\u96E8\u4F1E\u54E6\uFF01\uFF01\uFF01\n";
}
};
Cloudy = new Weather("Cloudy", 2, 3, "\u591A\u4E91") {
public String test() {
return "\u522B\u51FA\u53BB\u767B\u9AD8\u671B\u8FDC\u4E86\uFF0C\u4F60\u770B\u4E0D\u8FDC\u7684\uFF0C\u5475\u5475\u5475\uFF01\uFF01\uFF01\n";
}
};
ENUM$VALUES = (new Weather[] { Sunny, Rainy, Cloudy });
}
}
从上述我们可以看出, 枚举类的实现还是普通的java类, 只不过这个java类的构造函数是私有的, 而且实例的个数是有限个的, 当这个枚举类的实例个数只有一个的时候, 这个类就变成了单例模式了.