1.背景及定义
枚举是在JDK1.5以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式:
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLACK = 3;
但是常量举例有不好的地方,例如:可能碰巧有个数字1,但是他有可能误会为是RED,现在我们可以直接用枚举来进行组织,这样一来,就拥有了类型,枚举类型。而不是普通的整型1
public enum TestEnum {
RED,BLACK,GREEN;
}
.优点:将常量组织起来统一进行管理
场景:错误状态码,消息类型,颜色的划分,状态机等等....
本质:是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum,但是其默认继承了这个类。
2.枚举的使用
public enum TestEnum1 {
RED("red",1),BLACK("black",2),WHITE("white",3),GREEN("green",4);
private String name;
private int key;
// 1、当枚举对象有参数后 ,需要提供相应的构造函数
// 2、枚举的构造函数默认是私有的 这个一定要记住
private TestEnum1 (String name,int key) {
this.name = name;
this.key = key;
}
public static TestEnum1 getEnumKey (int key) {
for (TestEnum1 t: TestEnum1.values()) {
if(t.key == key) {
return t;
}
}
return null;
}
public static void main(String[] args) {
System.out.println(getEnumKey(2));
}
}
3.枚举的优点缺点
优点:
1. 枚举常量更简单安全 。
2. 枚举具有内置方法 ,代码更简洁。
缺点:
1. 不可继承,无法扩展。
4 枚举和反射
4.1 枚举是否可以通过反射,拿到实例对象呢?
我们刚刚在反射里边看到了,任何一个类,哪怕其构造方法是私有的,我们也可以通过反射拿到他的实例对象,那么枚举的构造方法也是私有的,我们是否可以拿到呢?接下来,我们来实验一下:
同样利用上述提供的枚举类来进行举例:
package demo1enum;
import java.lang.reflect.Constructor;
public enum TestEnum1 {
RED("red",1),BLACK("black",2),WHITE("white",3),GREEN("green",4);
private String name;
private int key;
// 1、当枚举对象有参数后 ,需要提供相应的构造函数
// 2、枚举的构造函数默认是私有的 这个一定要记住
private TestEnum1 (String name,int key) {
this.name = name;
this.key = key;
}
public static TestEnum1 getEnumKey (int key) {
for (TestEnum1 t: TestEnum1.values()) {
if(t.key == key) {
return t;
}
}
return null;
}
public static void reflectPrivateConstructor() {
try {
Class<?> classStudent = Class.forName("TestEnum");
//注意传入对应的参数,获得对应的构造方法来构造对象,当前枚举类是提供了两个参数分别是String和int。
Constructor<?> declaredConstructorStudent = classStudent.getDeclaredConstructor(String.class,int.class);
//设置为true后可修改访问权限
declaredConstructorStudent.setAccessible(true);
Object objectStudent = declaredConstructorStudent.newInstance("绿色",666);
TestEnum testEnum = (TestEnum) objectStudent;
System.out.println("获得枚举的私有构造函数 :"+testEnum);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
reflectPrivateConstructor();
}
}
输出结果:
意思是:就是没有对应的构造方法,我们所有的枚举类,都是默认继承于java.langEnum,它继承了父类除构造函数以外的所有东西,并且子类需要帮助父类进行构造,而我们并没有帮助父类进行构造,但也不用提供super,枚举比较特殊,他还默认添加了两个参数,看一下Enum的源码:
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
也就是说,我们自己的构造函数有两个参数一个是String一个是int,同时他默认后边还会给两个参数, 一个是 String一个是int。也就是说,这里我们正确给的是4个参数:
此时运行程序结果是:
此时的异常信息显示,是我的一个方法这个方法是:newInstance()报错了,我们来看一下这个方法的源码:
是的,枚举在这里被过滤了,你不能通过反射获取枚举类的实例!
5 总结
1、枚举本身就是一个类,其构造方法默认为私有的,且都是默认继承与java.langEnum
2、枚举可以避免反射和序列化问题
3、枚举的优点和缺点