原始的接口定义常量——一般定义常量的方法
public interface IConstants {
String MON = "Mon";
String TUE = "Tue";
String WED = "Wed";
String THU = "Thu";
String FRI = "Fri";
String SAT = "Sat";
String SUN = "Sun";
}
枚举语法(定义)
1、创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。2、枚举类型符合通用模式 Class Enum<E extends Enum<E>>,而 E 表示枚举类型的名称。
3、枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。
package com.hmw.test;
/**
* 枚举测试类
* @author <a href="mailto:[email protected]">何明旺</a>
*/
public enum EnumTest {
MON, TUE, WED, THU, FRI, SAT, SUN;
}
这段代码实际上调用了7次 Enum(String name, int ordinal):
new Enum<EnumTest>("MON",0);
new Enum<EnumTest>("TUE",1);
new Enum<EnumTest>("WED",2);
..............
遍历、switch 等常用操作
对enum进行遍历和switch的操作示例代码:
public class Test {
public static void main(String[] args) {
for (EnumTest e : EnumTest.values()) {
System.out.println(e.toString());
}
System.out.println("----------------我是分隔线------------------");
EnumTest test = EnumTest.TUE;
switch (test) {
case MON:
System.out.println("今天是星期一");
break;
case TUE:
System.out.println("今天是星期二");
break;
// ... ...
default:
System.out.println(test);
break;
}
}
}
输出结果为:
MON
TUE
WED
THU
FRI
SAT
SUN
----------------我是分隔线------------------
今天是星期二
enum 对象的常用方法介绍
1、比较此枚举与指定对象的顺序。
int compareTo(E o)
2、返回与此枚举常量的枚举类型相对应的 Class 对象。
Class<E> getDeclaringClass()
3、 返回此枚举常量的名称,在其枚举声明中对其进行声明。
String name()
4、返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
int ordinal()
5、 返回枚举常量的名称,它包含在声明中。
String toString()
6、返回带指定名称的指定枚举类型的枚举常量。
static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
public class Test {
public static void main(String[] args) {
EnumTest test = EnumTest.TUE;
//compareTo(E o)
switch (test.compareTo(EnumTest.MON)) {
case -1:
System.out.println("TUE 在 MON 之前");
break;
case 1:
System.out.println("TUE 在 MON 之后");
break;
default:
System.out.println("TUE 与 MON 在同一位置");
break;
}
//getDeclaringClass()
System.out.println("getDeclaringClass(): " + test.getDeclaringClass().getName());
//name() 和 toString()
System.out.println("name(): " + test.name());
System.out.println("toString(): " + test.toString());
//ordinal(), 返回值是从 0 开始
System.out.println("ordinal(): " + test.ordinal());
}
}
输出结果:
TUE 在 MON 之后
getDeclaringClass(): com.hmw.test.EnumTest
name(): TUE
toString(): TUE
ordinal(): 1
给 enum 自定义属性和方法
给 enum 对象加一下 value 的属性和 getValue() 的方法:
package com.hmw.test;
/**
* 枚举测试类
*
* @author <a href="mailto:[email protected]">何明旺</a>
*/
public enum EnumTest {
MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6) {
@Override
public boolean isRest() {
return true;
}
},
SUN(0) {
@Override
public boolean isRest() {
return true;
}
};
private int value;
private EnumTest(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public boolean isRest() {
return false;
}
}
public class Test {
public static void main(String[] args) {
System.out.println("EnumTest.FRI 的 value = " + EnumTest.FRI.getValue());
}
}
输出结果为:
EnumTest.FRI 的 value = 5
EnumSet,EnumMap 的应用
public class Test {
public static void main(String[] args) {
// EnumSet的使用
EnumSet<EnumTest> weekSet = EnumSet.allOf(EnumTest.class);
for (EnumTest day : weekSet) {
System.out.println(day);
}
// EnumMap的使用
EnumMap<EnumTest, String> weekMap = new EnumMap(EnumTest.class);
weekMap.put(EnumTest.MON, "星期一");
weekMap.put(EnumTest.TUE, "星期二");
// ... ...
for (Iterator<Entry<EnumTest, String>> iter = weekMap.entrySet().iterator(); iter.hasNext();) {
Entry<EnumTest, String> entry = iter.next();
System.out.println(entry.getKey().name() + ":" + entry.getValue());
}
}
}
原理分析
enum 的语法结构尽管和 class 的语法不一样,但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum<E>。
EnumTest 经过反编译(javap com.hmw.test.EnumTest 命令)之后得到的内容如下:
public class com.hmw.test.EnumTest extends java.lang.Enum{
public static final com.hmw.test.EnumTest MON;
public static final com.hmw.test.EnumTest TUE;
public static final com.hmw.test.EnumTest WED;
public static final com.hmw.test.EnumTest THU;
public static final com.hmw.test.EnumTest FRI;
public static final com.hmw.test.EnumTest SAT;
public static final com.hmw.test.EnumTest SUN;
static {};
public int getValue();
public boolean isRest();
public static com.hmw.test.EnumTest[] values();
public static com.hmw.test.EnumTest valueOf(java.lang.String);
com.hmw.test.EnumTest(java.lang.String, int, int, com.hmw.test.EnumTest);
}
所以,实际上 enum 就是一个 class,只不过 java 编译器帮我们做了语法的解析和编译而已。
总结
可以把 enum 看成是一个普通的 class,它们都可以定义一些属性和方法,
不同之处是:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)。
Java 枚举7常见种用法
用法一:常量
package javaEnum;
/**
* Created by cyg521 on 2018/1/17.
*/
//constant 常量
public class TestEnumByConstant {
//创建枚举类-----用法一常量
enum Color {
red , bule , white , black
}
public static void main(String[] args){
//测试枚举类-----用法一常量
System.out.println(Color.black);
System.out.println(Color.red);
System.out.println(Color.bule);
System.out.println(Color.white);
}
}
用法二:switch
package javaEnum;
/**
* Created by cyg521 on 2018/1/17.
*/
public class TestEnumBySwitch {
//创建枚举类-----用法二使用switch
enum Color2{
red , yeellow , green
}
Color2 c = Color2.green;
public void change(){
switch (c){
case red:
c = Color2.red;
System.out.println(c);
break;
case green:
c = Color2.green;
System.out.println(c);
break;
case yeellow:
c = Color2.yeellow;
System.out.println(c);
break;
}
}
public static void main(String[] args){
Color2[] d = Color2.values();
TestEnumBySwitch a = new TestEnumBySwitch();
a.change();
for (int i=0 ;i<d.length ; i++){
Color2 c = d[i];
System.out.println(d[i]);
switch (c){
case red:
c = Color2.red;
System.out.println(c);
break;
case green:
c = Color2.green;
System.out.println(c);
break;
case yeellow:
c = Color2.yeellow;
System.out.println(c);
break;
}
}
}
}
用法三:向枚举中添加新方法
package javaEnum;
import java.util.Scanner;
/**
* Created by cyg521 on 2018/1/17.
*/
//向枚举中添加新方法
public class TestEnumByAddNewMethod {
/**
* 如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。
* 可以理解为创建枚举的自定义方法编写
*/
enum Color{
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
//成员变量
private String name ;
private int index;
//构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//普通方法
public static String getName(int index){
for (Color c: Color.values()) {
if (c.getIndex() == index){
return c.name;
}
}
return null ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入代表颜色的下标1~4");
int i = sc.nextInt();
if( 0<=i&& i<=4){
System.out.println("你输入的颜色下标代表的颜色为: "+Color.getName(i));
}else {
System.out.println("你输入的颜色下标不存在对应的颜色;");
}
}
}
用法四:覆盖枚举的方法
package javaEnum;
/**
* Created by cyg521 on 2018/1/17.
*/
//覆盖枚举的方法
public class TestEnumByOverride {
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//覆盖方法
@Override
public String toString() {
return this.index+"_"+this.name;
}
}
public static void main(String[] args){
Color[] c = Color.values();
for (Color color:c) {
System.out.println(color.toString());
}
}
}
用法五:实现接口
package javaEnum;
/**
* Created by cyg521 on 2018/1/17.
*/
public class TestEnumByInterFace {
public enum Color implements Behaviour{
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//接口方法
@Override
public String getInfo() {
return this.name;
}
//接口方法
@Override
public void print() {
System.out.println(this.index+":"+this.name);
}
}
public static void main(String[] args){
Color[] colors = Color.values();
for (Color color:colors) {
System.out.println(color.getInfo());
color.print();
}
}
}
interface Behaviour {
void print();
String getInfo();
}
用法六:使用接口组织枚举
package javaEnum;
import com.sun.deploy.util.ArrayUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by cyg521 on 2018/1/17.
*/
public class TestEnumByInterfaces {
public interface Food {
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}
//数组合并方法
public static void main(String[] args){
Food[] foods1 = Food.Coffee.values();
Food[] foods2 = Food.Dessert.values();
List list = new ArrayList(Arrays.asList(foods1));
list.addAll(Arrays.asList(foods2));
Object[] foods = list.toArray();
for (Object food:foods) {
System.out.println(food);
}
System.out.println(Arrays.toString(foods));
}
}
用法七:关于枚举集合的使用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。关于枚举的实现细节和原理请参考:
参考资料:《ThinkingInJava》第四版