目录
一、枚举的意义
二、enum类的使用
1.switch
2.常用方法
2.1 values() 和 ordinal()
2.1.1 Enum基本介绍
2.2 valueOf()
2.3 compareTo()
三、枚举的优点和缺点
四、枚举安全在什么地方
一、枚举的意义
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLACK = 3;
让常量有类型,虽然final修饰的也可以做为常量但是如果代码其他地方有用到常量1,而不是代表RED那就会混淆意思。这个时候我们就可以用枚举。
public enum TestEnum {
RED,BLACK,GREEN;
}
注意:枚举类型默认继承了 java.lang.Enum ,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了 这个类。
二、enum类的使用
1.switch
public static void main(String[] args) {
EnumTest enumTest = RED;
switch (enumTest) {
case RED -> System.out.println(RED);
case BLACK -> System.out.println(BLACK);
case GREEN -> System.out.println(GREEN);
}
//输出RED
}
2.常用方法
Enum类的常用方法:
方法名称
|
描述
|
values()
|
以数组形式返回枚举类型的所有成员
|
ordinal()
|
获取枚举成员的索引位置
|
valueOf()
|
将普通字符串转换为枚举实例
|
compareTo()
|
比较两个枚举成员在定义时的顺序
|
2.1 values() 和 ordinal()
public static void main2(String[] args) {
EnumTest[] enumTests = EnumTest.values();
for (int i = 0; i < enumTests.length; i++) {
System.out.print(enumTests[i] + " " + enumTests[i].ordinal() + "\n");
}
}
结果:
2.1.1 Enum基本介绍
Enum的构造方法
Enum类只有这一个构造方法,但是我们写的枚举类并没有写构造方法,我们知道如果我们没写构造方法,会有一个没有任何参数的构造方法。但是父类只有这两个参数的构造方法。其实也是帮我们写了有两个参数的方法,传的值是null。所以枚举类是比较特殊的。
如果我们自己创建一个构造方法:
- 构造函数是
- zh当枚举对象有参数后,需要提供相应的构造函数
public enum EnumTest { //有了自己的构造方法,就必须在这里写的时候带参数 RED("red",0),BLACK("black",1),GREEN("green",2); private String name; private int key; /** * 1、当枚举对象有参数后,需要提供相应的构造函数 * 2、枚举的构造函数默认是私有的 这个一定要记住 * @param name * @param key */ private EnumTest(String name, int key) { this.name = name; this.key = key; } }
注意: 枚举内是不能手动创建对象的
那么问题来了,不创建对象怎么调用构造方法?
这也是为什么被说为是:枚举对象
name就做为名字,ordinal就做为创建的顺序。
我们也可以通过调试看看刚刚创建的数组是怎么样表示的:
ordinal()就是直接返回的ordinal
2.2 valueOf()
将普通字符串转换为枚举实例
字符串必须的以有的枚举对象,如果不是枚举对象会报错
public enum EnumTest {
RED("red",0),BLACK("black",1),GREEN("green",2);
public static void main(String[] args) {
EnumTest val = EnumTest.valueOf("BLACK");
System.out.println(val);
}
}
如果不是枚举对象:
结果:
2.3 compareTo()
比较两个枚举成员在定义时的顺序
public static void main(String[] args) {
//方式1 适合在枚举类内部使用
System.out.println(RED.compareTo(BLACK));
//方式2 适合在枚举类外时使用
EnumTest enumTest1 = EnumTest.RED;
EnumTest enumTest2 = EnumTest.BLACK;
System.out.println(enumTest1.compareTo(enumTest2));
}
结果:
根据ordinal的值比较
三、枚举的优点和缺点
优点:1. 枚举常量更简单安全 。2. 枚举具有内置方法 ,代码更优雅缺点:1. 不可继承,无法扩展
四、枚举安全在什么地方
我们知道利用反射无论是否是私有的,都可以被反射拿到甚至更改但是枚举是不可以的。
public static void reflectPrivateConstructor() {
Class<?> c1 = null;
try {
c1 = Class.forName("EnumTest");
//拿到构造方法
Constructor<EnumTest> constructor =
(Constructor<EnumTest>)c1.
//前两个传的是父类的构造方法参数,和两个是子类的构造方法参数
getDeclaredConstructor(String.class,int.class,String.class,int.class);
constructor.setAccessible(true);
//创建类的实例
EnumTest testEnum = constructor.newInstance("test",10,"白色",19);
System.out.println(testEnum);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public static void main4(String[] args) {
reflectPrivateConstructor();
}
警告:
是在这个函数出错的,我们去看看是什么问题
因为这一条判断语句,枚举类型不能被反射,所以枚举类型是安全的