Java枚举使用方式和注意事项
来源:互联网 发布:网络专线多少钱一年 编辑:程序博客网 时间:2024/06/08 12:49
枚举类型 是一组固定常量组成合法值的类型,比如一年中的季节,一周中的星期。
int枚举模式
不使用枚举时定义常量的方法通常是这样:
public final class Week { public static final int WEEK_MONDAY = 1; public static final int WEEK_TUESDAY = 2; public static final int WEEK_WEDNESDAY = 3; public static final int WEEK_THURSDAY = 4; public static final int WEEK_FRIDAY = 5; public static final int WEEK_SATURDAY = 6; public static final int WEEK_SUNDAY = 7;}
这种方法称作int枚举模式,这种方式有些缺点:
- 类型非安全,不能在编译期间发现问题,比如
setWeek(10)
或者setWeek(MONTH_JANUARY)
在语法上都是合法的,但你的本意并非如此。 - 可读性差,缺乏方便的方法把常量转换为有意义的字符串显示。
java1.5开始java提供一种新的引用类型 – 枚举类型(enum type)
定义枚举类型以及简单使用
/*** 定义了加、减、乘、除 操作*/public enum Operation { PLUS, MINUS, TIMES, DIVIDE}
//计算并打印结果public static void calc(int num1, int num2, Operation op) { switch (op) { case PLUS: System.out.println(num1 + " + " + num2 + " = "+num1 + num2); break; case MINUS: System.out.println(num1 - num2); break; case TIMES: System.out.println(num1 * num2); break; case DIVIDE: System.out.println(num1 / num2); break; default: throw new RuntimeException(); }} //调用计算方法 calc(1, 2, Operation.PLUS);//输出: 1 + 2 = 12
其中的
PLUS
MINUS
等都是Operation
类型,因此可以避免上面int枚举模式中类型安全问题,
可以利用编译器检查出类型不匹配。
枚举的一些特点
使用javap反编译上面的Operation.class
得到下面代码
public final class com.erick.hello.Operation extends java.lang.Enum<com.erick.hello.Operation> { public static final com.erick.hello.Operation PLUS; public static final com.erick.hello.Operation MINUS; public static final com.erick.hello.Operation TIMES; public static final com.erick.hello.Operation DIVIDE; static {}; public static com.erick.hello.Operation[] values(); public static com.erick.hello.Operation valueOf(java.lang.String);}
通过上面反编译的结果可以知道:
- Operation隐式继承了
java.lang.Enum
,Enum
实现了Comparable<E>
Serializable
这两个接口。 - Operation不能再继承其他类,但可以实现其他接口。
- Operation是final的,所以不能被扩展。但这不是真正原因,真正的限制应该是编译器做的限制。
- 新生成了两个方法
values()
valueOf(String)
- 定义的每一个枚举值实际上都是一个
Operation
类型的实例
除了完善了int枚举类型的不足之外,枚举类型还可以添加任意的方法和属性,并且可以实现任意接口。
添加任意方法的原因可能是想要将数据或者操作与对应的常量关联。
为枚举增加属性和方法
/** * 定义了加、减、乘、除 操作 */public enum Operation { //枚举常量的定义必须在第一行,最后一个常量后面加分号,后面是定义的属性和方法 PLUS("+"), MINUS("-"), TIMES("*"), DIVIDE("/"); private String op; private Operation(String op) { this.op = op; } public String getOP() { return op; } public void calc(int num1, int num2) { switch (this) { case PLUS: System.out.println(num1 + op + num2 + " = " + (num1 + num2)); break; case MINUS: System.out.println(num1 - num2); break; case TIMES: System.out.println(num1 * num2); break; case DIVIDE: System.out.println(num1 / num2); break; default: throw new RuntimeException(); } }}//测试Operation.PLUS.calc(1, 2);//输出:1+2 = 3
上面的例子中如果想要增加一个开方运算,就需要增加一个开方枚举,并在switch case 中加一个分支来做具体运算。
但是这样很容易只添加了开方枚举,但忘记了具体运算的实现,而且能够顺利编译。下面的方法可以尽量避免这一情况。
public enum Operation { PLUS("+") { @Override void calc(int num1, int num2) { System.out.println(num1 + this.getOP() + num2 + " = " + (num1 + num2)); } }, MINUS("-") { @Override void calc(int num1, int num2) { System.out.println(num1 + this.getOP() + num2 + " = " + (num1 + num2)); } }; private String op; private Operation(String op) { this.op = op; } public String getOP() { return op; } abstract void calc(int num1, int num2);}
枚举中通用的方法
//比较此枚举与指定对象的顺序。int compareTo(E o) //返回与此枚举常量的枚举类型相对应的 Class 对象。Class<E> getDeclaringClass() //返回此枚举常量的名称,在其枚举声明中对其进行声明。String name() //与name()返回一致String toString()//返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。int ordinal() //返回带指定名称的指定枚举类型的枚举常量。static <T extends Enum<T>> T valueOf(String name) //测试for(Operation o : Operation.values()){ System.out.println(o.ordinal() + " : " + o.name() + " : " + o.getDeclaringClass());}// 输出:// 0 : PLUS : class com.erick.hello.Operation// 1 : MINUS : class com.erick.hello.Operation// 2 : TIMES : class com.erick.hello.Operation// 3 : DIVIDE : class com.erick.hello.Operation
ordinal()的使用
大多数情况下不需要使用这个方法,这个方法的设计是用于像EnumSet和EnumMap这种基于枚举通用数据结构的,
除非是编写这些数据结构,否则应该避免使用ordinal方法。如果需要枚举与一个int值绑定,应该使用枚举实例的属性来绑定。
public enum Week { WEEK_MONDAY(1), WEEK_TUESDAY(2); private int num; Week(int num) { this.num = num; }}
使用接口模拟可伸缩的枚举
枚举类型不能被继承,这是语言特性,而且枚举是用来表示有限数量的对象,因此大多情况下并不需要扩展。
但有些情况,比如一些特特定操作,当下只包括了所有操作的一部分就可以满足需求,
但需要更多操作时就需要扩展。
上面的计算器例子中,实现了计算器的加、减、乘、除操作,但之后又需要一个求幂的操作,
这时可以实现一个操作接口,来实现可扩展的特性。
//操作接口public interface Operation { void calc(int num1, int num2);}//基础计算枚举public enum BasicOperation implements Operation{ //....省略了减法和乘除。 PLUS("+") { @Override public void calc(int num1, int num2) { System.out.println(num1 + this.getOP() + num2 + " = " + (num1 + num2)); } }; private String op; private BasicOperation(String op) { this.op = op; } public String getOP() { return op; }}//扩展一个幂运算public enum ExtendedOperation implements Operation{ PLUS("^") { @Override public void calc(int num1, int num2) { System.out.println(num1 + this.getOP() + num2 + " = " + Math.pow(num1, num2)); } }; private String op; private ExtendedOperation(String op) { this.op = op; } public String getOP() { return op; }}
只要API通过接口的方式操作,就可以允许客户端扩展自己的操作方式。
- Java枚举使用方式和注意事项
- 文件使用方式和注意事项
- Java枚举的几种使用方式
- Android Handler的使用方式和注意事项
- 使用枚举类型的注意事项
- JAVA 中枚举类注意事项
- java枚举创建,定义注意事项
- Java中枚举类型Enum的一种使用方式
- Java中枚举类型Enum的一种使用方式
- java枚举和Struts2的使用
- 关于java枚举使用和理解。
- java 枚举的学习和使用
- Java枚举类型的使用和原理
- Java 使用 switch 语句和枚举类型
- java使用mongoDB和freemarker的注意事项
- Java socket 使用BufferedReader和BufferedWriter注意事项
- java中ArrayList和LinkedList使用注意事项
- Tomcat和Java及servlet使用注意事项
- leetcode--字符串循环左移
- 高精度算式计算(加法和乘法)
- 并查集 最小生成树
- ImageBrowser
- 如何提高思维能力,做一个有思想的人
- Java枚举使用方式和注意事项
- Java环境变量之Path和classpath
- Android中pull解析xml文件
- 基础篇章:React Native 之 TextInput 的讲解
- 【C#】45. Task ContinueWith 后续操作
- 查找最小的k个元素
- 【Leetcode】8. String to Integer (atoi)
- 3379 数据结构实验之查找七:线性之哈希表
- 超简单的viewpage指示器