枚举的定义
枚举在很多语言里面都有定义,在实际中有广泛用途。java中enum将一组具名的值的有限集合创建为一种新的类型,具名的值有点和常量类似。
举个简单的例子,不用枚举时我们定义一周的方式
public class DayDemo {
public static final int MONDAY =1;
public static final int TUESDAY=2;
public static final int WEDNESDAY=3;
public static final int THURSDAY=4;
public static final int FRIDAY=5;
public static final int SATURDAY=6;
public static final int SUNDAY=7;
}
这里存在类型不安全的问题,可能重复定义int相同的值。现在我们用枚举来定义
enum Day {
MONDAY, TUESDAY, WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}
使用枚举简洁了许多,其实编译的时候枚举变量还是转换成了final常量,在本文最后的反编译文件里面可以看到。当然了,枚举不是简单地将整形数值转换成对象,一方面增加了多个很实用的方法和变量,比如values(), compareTo等方法,另一方面增加了安全性,不能手动调用构造方法构建对象,就连反射的方法也被堵死了。
枚举其实也是一个类,可以增加方法和属性,也可以实现接口。枚举相比普通的类有几个不同的点:
1.枚举构造方法只能private, 只能供编译器调用;
2.枚举不能继承;
枚举在编译时会添加很多方法,下面将列举一下:
方法名 | 方法说明 |
---|---|
name() | 获取此枚举常量的名称,在其枚举声明中对其进行声明 |
ordinal() | 获取枚举常量的位置,从0开始 |
values() | 获取枚举中的所有枚举常量 |
getDeclaringClass() | 获取枚举常量的class对象 |
valueOf(String name) | 获取返回带指定名称的指定枚举类型的枚举常量 |
现在我们继续深入一下代码
/**
* Returns the Class object corresponding to this enum constant's
* enum type. Two enum constants e1 and e2 are of the
* same enum type if and only if
* e1.getDeclaringClass() == e2.getDeclaringClass().
* (The value returned by this method may differ from the one returned
* by the {@link Object#getClass} method for enum constants with
* constant-specific class bodies.)
*
* @return the Class object corresponding to this enum constant's
* enum type
*/
@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
//获取class对象的应用,getClass()是object的方法
Class<?> clazz = getClass();
//获取父类Class对象的引用
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) {
//enumType.enumConstantDirectory()获取到的是一个map集合,key值就是name值,value则是枚举变量值
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);
}
可惜,values()是编译器生成的static方法,没有找到其对应实现代码。
闲话不多说,下面将写一个样例。
public enum EnumDemo {
//定义枚举类型
MONDAY(0, "monday"),
TUESDAY(1, "tuesday"),
WEDNESDAY(2, "wednesday"),
THURSDAY(3, "thursday"),
FRIDAY(4, "friday"),
SATURDAY(5, "saturday"),
SUNDAY(6, "sunday");
int code;
String message;
//自定义构造函数
EnumDemo(int code, String message) {
this.code = code;
this.message = message;
}
public static EnumDemo getByCode(int code) {
for (EnumDemo day : EnumDemo.values()) {
if (day.code == code) {
return day;
}
}
return null;
}
public static void main(String[] args) {
System.out.println(EnumDemo.values());
for (EnumDemo day : EnumDemo.values()) {
System.out.println(day.name() + ": " + day.ordinal());
}
EnumDemo monday = EnumDemo.valueOf("MONDAY");
System.out.println(getByCode(5));
System.out.println(monday.getDeclaringClass());
System.out.println(monday.getDeclaringClass().getEnumConstants());
//枚举和switch非常搭配,下面演示在switch的用法
switch(monday) {
//注意MONDAY前面不需要加包名
case MONDAY:
System.out.println(MONDAY.name() + ": " + MONDAY.ordinal());
break;
case TUESDAY:
System.out.println(TUESDAY.name() + ": " + TUESDAY.ordinal());
break;
case WEDNESDAY:
System.out.println(WEDNESDAY.name() + ": " + WEDNESDAY.ordinal());
break;
case THURSDAY:
System.out.println(THURSDAY.name() + ": " + THURSDAY.ordinal());
break;
case FRIDAY:
System.out.println(FRIDAY.name() + ": " + FRIDAY.ordinal());
break;
case SATURDAY:
System.out.println(SATURDAY.name() + ": " + SATURDAY.ordinal());
break;
case SUNDAY:
System.out.println(SUNDAY.name() + ": " + SUNDAY.ordinal());
break;
default:
System.out.println("not found");
break;
}
}
}
运行结果:
[LEnumDemo;@2503dbd3
MONDAY: 0
TUESDAY: 1
WEDNESDAY: 2
THURSDAY: 3
FRIDAY: 4
SATURDAY: 5
SUNDAY: 6
EnumDemo{code=5, message='saturday'}
class EnumDemo
[LEnumDemo;@4b67cf4d
MONDAY: 0
枚举与接口
EnumSet
EnumSet存储的枚举常量,因为枚举是有限的,内部使用的是bit-vector方式,大大提高节省了存储空间和查找效率;
EnumMap
与EnumSet相同,使用的是枚举常量作为键值。
最后附上demo的反编译文件
public final class EnumDemo extends java.lang.Enum<EnumDemo> {
public static final EnumDemo MONDAY;
public static final EnumDemo TUESDAY;
public static final EnumDemo WEDNESDAY;
public static final EnumDemo THURSDAY;
public static final EnumDemo FRIDAY;
public static final EnumDemo SATURDAY;
public static final EnumDemo SUNDAY;
int code;
java.lang.String message;
public static EnumDemo[] values();
Code:
0: getstatic #1 // Field $VALUES:[LEnumDemo;
3: invokevirtual #2 // Method "[LEnumDemo;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LEnumDemo;"
9: areturn
public static EnumDemo valueOf(java.lang.String);
Code:
0: ldc #4 // class EnumDemo
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class EnumDemo
9: areturn
public java.lang.String toString();
Code:
0: new #9 // class java/lang/StringBuilder
3: dup
4: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
7: ldc #11 // String EnumDemo{code=
9: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: aload_0
13: getfield #7 // Field code:I
16: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
19: ldc #14 // String , message='
21: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: aload_0
25: getfield #8 // Field message:Ljava/lang/String;
28: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
31: bipush 39
33: invokevirtual #15 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
36: bipush 125
38: invokevirtual #15 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
41: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
44: areturn
public static EnumDemo getByCode(int);
Code:
0: invokestatic #17 // Method values:()[LEnumDemo;
3: astore_1
4: aload_1
5: arraylength
6: istore_2
7: iconst_0
8: istore_3
9: iload_3
10: iload_2
11: if_icmpge 37
14: aload_1
15: iload_3
16: aaload
17: astore 4
19: aload 4
21: getfield #7 // Field code:I
24: iload_0
25: if_icmpne 31
28: aload 4
30: areturn
31: iinc 3, 1
34: goto 9
37: aconst_null
38: areturn
public static void main(java.lang.String[]);
Code:
0: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #17 // Method values:()[LEnumDemo;
6: invokevirtual #19 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
9: invokestatic #17 // Method values:()[LEnumDemo;
12: astore_1
13: aload_1
14: arraylength
15: istore_2
16: iconst_0
17: istore_3
18: iload_3
19: iload_2
20: if_icmpge 71
23: aload_1
24: iload_3
25: aaload
26: astore 4
28: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
31: new #9 // class java/lang/StringBuilder
34: dup
35: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
38: aload 4
40: invokevirtual #20 // Method name:()Ljava/lang/String;
43: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
46: ldc #21 // String :
48: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
51: aload 4
53: invokevirtual #22 // Method ordinal:()I
56: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
59: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
62: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
65: iinc 3, 1
68: goto 18
71: ldc #24 // String MONDAY
73: invokestatic #25 // Method valueOf:(Ljava/lang/String;)LEnumDemo;
76: astore_1
77: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
80: iconst_5
81: invokestatic #26 // Method getByCode:(I)LEnumDemo;
84: invokevirtual #19 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
87: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
90: aload_1
91: invokevirtual #27 // Method getDeclaringClass:()Ljava/lang/Class;
94: invokevirtual #19 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
97: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
100: aload_1
101: invokevirtual #27 // Method getDeclaringClass:()Ljava/lang/Class;
104: invokevirtual #28 // Method java/lang/Class.getEnumConstants:()[Ljava/lang/Object;
107: invokevirtual #19 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
110: getstatic #29 // Field EnumDemo$1.$SwitchMap$EnumDemo:[I
113: aload_1
114: invokevirtual #22 // Method ordinal:()I
117: iaload
118: tableswitch { // 1 to 7
1: 160
2: 202
3: 244
4: 286
5: 328
6: 370
7: 412
default: 454
}
160: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
163: new #9 // class java/lang/StringBuilder
166: dup
167: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
170: getstatic #30 // Field MONDAY:LEnumDemo;
173: invokevirtual #20 // Method name:()Ljava/lang/String;
176: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
179: ldc #21 // String :
181: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
184: getstatic #30 // Field MONDAY:LEnumDemo;
187: invokevirtual #22 // Method ordinal:()I
190: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
193: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
196: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
199: goto 462
202: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
205: new #9 // class java/lang/StringBuilder
208: dup
209: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
212: getstatic #31 // Field TUESDAY:LEnumDemo;
215: invokevirtual #20 // Method name:()Ljava/lang/String;
218: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
221: ldc #21 // String :
223: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
226: getstatic #31 // Field TUESDAY:LEnumDemo;
229: invokevirtual #22 // Method ordinal:()I
232: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
235: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
238: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
241: goto 462
244: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
247: new #9 // class java/lang/StringBuilder
250: dup
251: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
254: getstatic #32 // Field WEDNESDAY:LEnumDemo;
257: invokevirtual #20 // Method name:()Ljava/lang/String;
260: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
263: ldc #21 // String :
265: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
268: getstatic #32 // Field WEDNESDAY:LEnumDemo;
271: invokevirtual #22 // Method ordinal:()I
274: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
277: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
280: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
283: goto 462
286: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
289: new #9 // class java/lang/StringBuilder
292: dup
293: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
296: getstatic #33 // Field THURSDAY:LEnumDemo;
299: invokevirtual #20 // Method name:()Ljava/lang/String;
302: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
305: ldc #21 // String :
307: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
310: getstatic #33 // Field THURSDAY:LEnumDemo;
313: invokevirtual #22 // Method ordinal:()I
316: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
319: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
322: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
325: goto 462
328: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
331: new #9 // class java/lang/StringBuilder
334: dup
335: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
338: getstatic #34 // Field FRIDAY:LEnumDemo;
341: invokevirtual #20 // Method name:()Ljava/lang/String;
344: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
347: ldc #21 // String :
349: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
352: getstatic #34 // Field FRIDAY:LEnumDemo;
355: invokevirtual #22 // Method ordinal:()I
358: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
361: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
364: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
367: goto 462
370: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
373: new #9 // class java/lang/StringBuilder
376: dup
377: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
380: getstatic #35 // Field SATURDAY:LEnumDemo;
383: invokevirtual #20 // Method name:()Ljava/lang/String;
386: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
389: ldc #21 // String :
391: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
394: getstatic #35 // Field SATURDAY:LEnumDemo;
397: invokevirtual #22 // Method ordinal:()I
400: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
403: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
406: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
409: goto 462
412: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
415: new #9 // class java/lang/StringBuilder
418: dup
419: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
422: getstatic #36 // Field SUNDAY:LEnumDemo;
425: invokevirtual #20 // Method name:()Ljava/lang/String;
428: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
431: ldc #21 // String :
433: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
436: getstatic #36 // Field SUNDAY:LEnumDemo;
439: invokevirtual #22 // Method ordinal:()I
442: invokevirtual #13 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
445: invokevirtual #16 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
448: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
451: goto 462
454: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
457: ldc #37 // String not found
459: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
462: return
static {};
Code:
0: new #4 // class EnumDemo
3: dup
4: ldc #24 // String MONDAY
6: iconst_0
7: iconst_0
8: ldc #38 // String monday
10: invokespecial #39 // Method "<init>":(Ljava/lang/String;IILjava/lang/String;)V
13: putstatic #30 // Field MONDAY:LEnumDemo;
16: new #4 // class EnumDemo
19: dup
20: ldc #40 // String TUESDAY
22: iconst_1
23: iconst_1
24: ldc #41 // String tuesday
26: invokespecial #39 // Method "<init>":(Ljava/lang/String;IILjava/lang/String;)V
29: putstatic #31 // Field TUESDAY:LEnumDemo;
32: new #4 // class EnumDemo
35: dup
36: ldc #42 // String WEDNESDAY
38: iconst_2
39: iconst_2
40: ldc #43 // String wednesday
42: invokespecial #39 // Method "<init>":(Ljava/lang/String;IILjava/lang/String;)V
45: putstatic #32 // Field WEDNESDAY:LEnumDemo;
48: new #4 // class EnumDemo
51: dup
52: ldc #44 // String THURSDAY
54: iconst_3
55: iconst_3
56: ldc #45 // String thursday
58: invokespecial #39 // Method "<init>":(Ljava/lang/String;IILjava/lang/String;)V
61: putstatic #33 // Field THURSDAY:LEnumDemo;
64: new #4 // class EnumDemo
67: dup
68: ldc #46 // String FRIDAY
70: iconst_4
71: iconst_4
72: ldc #47 // String friday
74: invokespecial #39 // Method "<init>":(Ljava/lang/String;IILjava/lang/String;)V
77: putstatic #34 // Field FRIDAY:LEnumDemo;
80: new #4 // class EnumDemo
83: dup
84: ldc #48 // String SATURDAY
86: iconst_5
87: iconst_5
88: ldc #49 // String saturday
90: invokespecial #39 // Method "<init>":(Ljava/lang/String;IILjava/lang/String;)V
93: putstatic #35 // Field SATURDAY:LEnumDemo;
96: new #4 // class EnumDemo
99: dup
100: ldc #50 // String SUNDAY
102: bipush 6
104: bipush 6
106: ldc #51 // String sunday
108: invokespecial #39 // Method "<init>":(Ljava/lang/String;IILjava/lang/String;)V
111: putstatic #36 // Field SUNDAY:LEnumDemo;
114: bipush 7
116: anewarray #4 // class EnumDemo
119: dup
120: iconst_0
121: getstatic #30 // Field MONDAY:LEnumDemo;
124: aastore
125: dup
126: iconst_1
127: getstatic #31 // Field TUESDAY:LEnumDemo;
130: aastore
131: dup
132: iconst_2
133: getstatic #32 // Field WEDNESDAY:LEnumDemo;
136: aastore
137: dup
138: iconst_3
139: getstatic #33 // Field THURSDAY:LEnumDemo;
142: aastore
143: dup
144: iconst_4
145: getstatic #34 // Field FRIDAY:LEnumDemo;
148: aastore
149: dup
150: iconst_5
151: getstatic #35 // Field SATURDAY:LEnumDemo;
154: aastore
155: dup
156: bipush 6
158: getstatic #36 // Field SUNDAY:LEnumDemo;
161: aastore
162: putstatic #1 // Field $VALUES:[LEnumDemo;
165: return
参考:
1.https://blog.csdn.net/javazejian/article/details/71333103
2.https://www.ibm.com/developerworks/cn/java/j-lo-enum/index.html
网友评论