定义
Java 代码的两个基本的构造块是 类和 接口。现在又引入了 枚举,一般简称它为enum。这个新类型允许您表示特定的数据点,这些数据点只接受分配时预先定义的值集合。
当然,熟练的程序员可以用静态常量实现这项功能,如清单 1 所示:
public class OldGrade {
public static final int A = 1;
public static final int B = 2;
public static final int C = 3;
public static final int D = 4;
public static final int F = 5;
public static final int INCOMPLETE = 6;
}
然后您就可以让类接受像 OldGrade.B 这样的常量,但是在这样做的时候,请记住这类常量是 Java 中 int 类型的常量,这意味着该方法可以接受任何 int 类型的值,即使它和 OldGrade 中定义的所有级别都不对应。因此,您需要检测上界和下界,在出现无效值的时候,可能还要包含一个 IllegalArgumentException 。而且,如果后来又添加另外一个级别(例如 OldGrade.WITHDREW_PASSING ),那么必须改变所有代码中的上界,才能接受这个新值。
换句话说,在使用这类带有整型常量的类时,该解决方案也许可行,但并不是非常有效。幸运的是,枚举提供了更好的方法。
定义枚举
public enum Grade {
A, B, C, D, F, INCOMPLETE
};
在这里,我使用了新的关键字 enum ,为 enum 提供了一个名称,并指定了允许的值。然后, Grade 就变成了一个 枚举类型,您可以按清单 3 所示的方法使用它:
package com.oreilly.tiger.ch03;
public class Student {
private String firstName;
private String lastName;
private Grade grade;
public Student(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return new StringBuffer(firstName)
.append(" ")
.append(lastName)
.toString();
}
public void assignGrade(Grade grade) {
this.grade = grade;
}
public Grade getGrade() {
return grade;
}
}
用以前定义过的类型建立一个新的枚举( grade )之后,您就可以像使用其他成员变量一样使用它了。当然,枚举只能分配枚举值中的一个(例如, A 、 C 或 INCOMPLETE )。而且,在 assignGrade() 中是没有进行错误检测的代码,也没有考虑边界情况,请注意这是如何做到。
Java 枚举7常见种用法
enum关键字的作用类似于class或interface,本质上是在定义一个类别,细节的实现由编译器完成。
自定义的枚举类型实质上继承自java.lang.Enum抽象类。而每一个成员常量其实就是自己定义的枚举类型的一个实例,都被定义为final,所有无法改变他们,另外他们是static,pulibc的,即:
public static final 枚举常量;
在运行期间我们无法再使用该枚举类型创建新的实例,这些实例是在编译期间就完全确定下来了的。
枚举类型中的两个静态方法:
values()
获取枚举类型的所有枚举常量
valueOf(Class enumType, String name)
返回带指定名称的指定枚举类型的枚举常量。
用法一:常量
在JDK1.5 之前,我们定义常量都是: publicstaticfianl…. 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。
1. public enum Color {
2. RED, GREEN, BLANK, YELLOW
3. }
用法二:switch
JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。
Java代码
1. enum Signal {
2. GREEN, YELLOW, RED
3. }
4. public class TrafficLight {
5. Signal color = Signal.RED;
6. public void change() {
7. switch (color) {
8. case RED:
9. color = Signal.GREEN;
10. break;
11. case YELLOW:
12. color = Signal.RED;
13. break;
14. case GREEN:
15. color = Signal.YELLOW;
16. break;
17. }
18. }
19. }
用法三:向枚举中添加新方法
如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。
Java代码
1. public enum Color {
2. RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
3. // 成员变量
4. private String name;
5. private int index;
6. // 构造方法
7. private Color(String name, int index) {
8. this.name = name;
9. this.index = index;
10. }
11. // 普通方法
12. public static String getName(int index) {
13. for (Color c : Color.values()) {
14. if (c.getIndex() == index) {
15. return c.name;
16. }
17. }
18. return null;
19. }
20. // get set 方法
21. public String getName() {
22. return name;
23. }
24. public void setName(String name) {
25. this.name = name;
26. }
27. public int getIndex() {
28. return index;
29. }
30. public void setIndex(int index) {
31. this.index = index;
32. }
33. }
用法四:覆盖枚举的方法
下面给出一个toString()方法覆盖的例子。
Java代码
1. public enum Color {
2. RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
3. // 成员变量
4. private String name;
5. private int index;
6. // 构造方法
7. private Color(String name, int index) {
8. this.name = name;
9. this.index = index;
10. }
11. //覆盖方法
12. @Override
13. public String toString() {
14. return this.index+"_"+this.name;
15. }
16. }
用法五:实现接口
所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
Java代码
1. public interface Behaviour {
2. void print();
3. String getInfo();
4. }
5. public enum Color implements Behaviour{
6. RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
7. // 成员变量
8. private String name;
9. private int index;
10. // 构造方法
11. private Color(String name, int index) {
12. this.name = name;
13. this.index = index;
14. }
15. //接口方法
16. @Override
17. public String getInfo() {
18. return this.name;
19. }
20. //接口方法
21. @Override
22. public void print() {
23. System.out.println(this.index+":"+this.name);
24. }
25. }
用法六:使用接口组织枚举
Java代码
1. public interface Food {
2. enum Coffee implements Food{
3. BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
4. }
5. enum Dessert implements Food{
6. FRUIT, CAKE, GELATO
7. }
8. }
用法七:关于枚举集合的使用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。
关于枚举的实现细节和原理请参考:
参考资料:《ThinkingInJava》第四版
http://softbeta.iteye.com/blog/1185573
Java 枚举:switch 支持枚举demo
package mark.demo;
import java.util.Random;
public class EnumDemo {
public static void main(String[] args) {
int len = Color.values().length;
Color color = Color.getColor(len);
switch (color) {
case RED:
System.out.println("select " + "RED");
break;
case GREEN:
System.out.println("select " + "GREEN");
break;
case BLUE:
System.out.println("select " + "BLUE");
break;
case YELLOW:
System.out.println("select " + "YELLOW");
break;
default:
System.out.println("select " + "unknow!!");
break;
}
}
public enum Color {
RED("red color", 0),
GREEN("green color", 1),
BLUE("blue color", 2),
YELLOW("yellow color", 3);
Color(String name, int id) {
_name = name;
_id = id;
}
private String _name;
private int _id;
public String getName() {
return _name;
}
public int getId() {
return _id;
}
public static Color getColor(int max) {
Random random = new Random(System.currentTimeMillis());
int num = random.nextInt(max);
switch (num) {
case 0:
return Color.RED;
case 1:
return Color.GREEN;
case 2:
return Color.BLUE;
case 3:
return Color.YELLOW;
default:
return Color.BLUE;
}
}
}
}
枚举和静态常量的区别是什么
常量是直接编译在代码中的,而枚举则是一种类,你可以通过反射根据值反查出它的枚举形式是什么。
枚举定义了值的范围,但是常量没有。所以要根据你的实际情况选择。比如你有一个变量,是中国所有的省,那么最好用枚举,因为这些是固定不变的。在代码里使用的时候更方便,也易懂。
常量不是数据类型,只是说明被定义数据是不可变的常量还是可变变量;枚举是一种数据类型。
枚举定义了一组业务类型相同的成员且成员的语义清晰;常量也可以是一个基础类型的数组,比如int[],虽然业务类型那个上这些元素可能是一类的,但是没法清晰指出其中元素的意义。
枚举类是为了让自己更直接的知道 每个常量所代表的意义 同时也给该类型的变量一个取值的限制
定义一种枚举类型(就像int类型一样)后,声明的枚举类型变量(就像 int i;中的i),枚举类型变量的取值范围被限定为之前枚举类型中定义的值。常量就是不能变的量,如字符A,数字1,或者用const声明的不能再被赋值的变量。
枚举定义了一个变量的可使用范围。另外,能够是程序可读性提高。