浅谈 Java 中的枚举
枚举也就是一一列举,常用来表示那些可以明确范围的集合,比方说性别,季节,星期,月份等。
在 JDK 1.5 才出现枚举类,在没有出现枚举类之前,我们要表示几个确定的值通常会使用常量来表示,形如
public static final Integer SPRING = 1;
public static final Integer SUMMER = 2;
public static final Integer FALL = 3;
public static final Integer WINTER = 4;
我们可以使用枚举类来表示,这也就是最简单的枚举。
enum Season{
SPRING,SUMMER,FALL,WINTER;
}
那么枚举类和定义常量相比有什么优势呢?
安全,我们看上面的代码可以知道,使用常量表示的季节都是 Integer 类型的,而这个类型的数据范围太大了,而使用枚举就限制了数据的域。枚举可以理解为几个常量的集合,数据不太会改变,使用枚举之后语义更加明确,因为数据域不大。
关于枚举类,有几点需要注意:
enum 和 class ,interface 的地位一样
使用 enum 定义的枚举类默认继承了 java.lang.Enum,而不是继承 Object 类。枚举类可以实现一个或多个接口,不能再继承其他类了。
枚举类的所有实例都必须放在第一行展示,不需使用 new 关键字,不需显式调用构造器。自动添加 public static final 修饰。
枚举类的构造器只能是私有的。
关于第 4 点,我要说枚举类的定义是单例模式的,单例模式要求构造器私有化,不允许在外部创建新的对象,你想呀,枚举类的作用就是准确的表示出同一类别下的不同数据。在我们定义的时候已经创建好了,所以跟本不需要也不能在外部继续创建新的对象。故,需要将构造器私有化。
枚举类说的通俗点就是被阉割的类,我们使用类可以创建对象,而枚举类在定义的时候就会指定创建的对象有哪些。你没有显示的写代码创建,不过是由于 JVM 自动给你加上去了。待会看看枚举类被反编译之后的情况就会理解。
枚举类中可以定义属性和方法。
enum Season{
SPRING("春天","一年之计在于春"),SUMMER("夏天","夏天好热 ~ "),
FALL("秋天","秋水共长天一色"),WINTER("冬天","冬天好冷 ~ ");
// 添加枚举对象的名称
private final String name;
// 添加枚举对象的描述
private final String desc;
private Season(String name,String desc){
this.name = name;
this.desc = desc;
}
public String getName(){
return name;
}
public String getDesc(){
return desc;
}
}
我们可以看到,有一个带参的私有构造函数,所以在定义枚举的时候可以直接赋值,而调用创建对象是由虚拟机自动完成的,还可以添加更多的属性,我们可以正常使用枚举对象。
// 获取所有的枚举对象,返回的是数组
Season[] values = Season.values();
for (Season season : values) {
System.out.println(season.getName() + " : " + season.getDesc());
} 春天 : 一年之计在于春
夏天 : 夏天好热 ~
秋天 : 秋水共长天一色
冬天 : 冬天好冷 ~
枚举类中实现抽象方法
这肯定有点迷糊,我们知道含有抽象方法的类是抽象类,那为什么枚举类不是 abstract 的也可以含有抽象方法呢 ?我们先来看看实现,待会说原因。
enum Season{
SPRING("春天","一年之计在于春") {
@Override
public Season getNextSeason() {
return Season.valueOf("SUMMER");
}
},SUMMER("夏天","夏天好热 ~ ") {
@Override
public Season getNextSeason() {
return Season.valueOf("FALL");
}
},
... 省略
... 省略
... 省略
// 定义了一个抽象方法,获取下一个季节
public abstract Season getNextSeason();
}
测试代码如下
public static void main(String[] args) {
String name = Season.SPRING.getNextSeason().getName();
System.out.println(name); // 夏天
}
是不是有种似懂非懂的感觉,没关系,我们来反编译看一看枚举类的内部构造你就会明白。
举个简单的例子来看一看枚举类的原理。就拿一个最简单的枚举来说明情况。
public enum SeasonEnum {
SPRING,SUMMER,FALL,WINTER;
}
看一看反编译之后的代码,我使用的反编译工具是 jad 。
public final class SeasonEnum extends Enum
{ public static SeasonEnum[] values()
{
return (SeasonEnum[])$VALUES.clone();
} public static SeasonEnum valueOf(String s)
{
return (SeasonEnum)Enum.valueOf(SeasonEnum, s);
} private SeasonEnum(String s, int i)
{
super(s, i);
} public static final SeasonEnum SPRING;
public static final SeasonEnum SUMMER;
public static final SeasonEnum FALL;
public static final SeasonEnum WINTER;
private static final SeasonEnum $VALUES[]; static
{
SPRING = new SeasonEnum("SPRING", 0);
SUMMER = new SeasonEnum("SUMMER", 1);
FALL = new SeasonEnum("FALL", 2);
WINTER = new SeasonEnum("WINTER", 3);
$VALUES = (new SeasonEnum[] {
SPRING, SUMMER, FALL, WINTER
});
}
}
可以看到枚举类本质上就是一个继承了 Enum 的一个单例最终类,而我们定义的枚举对象也是在静态代码块中初始化了,同时我们也可以看到 values 方法的实现就是返回实例对象的数组,也就是枚举对象的数组,valueOf 方法接收一个字符串,返回的是字符串对应的枚举对象,若是找不到,会报错。
看到这我们也就能理解为什么我们可以在枚举类中定义抽象方法了,我们使用内部类实现了抽象方法,对应的每个对象在创建时都会实现相应的抽象方法。同样的道理,枚举类也可以实现接口,这里就不演示了。
说了这么多,也知道了枚举的好处,但是不得不说的是我在实际的项目中,枚举类的使用还真不多,下面就看看枚举类可以有哪些用处,以后有这种需求就可以考虑使用枚举来实现。
switch 语句支持枚举类型是从 JDK 1.5 才开始的,因为此时才有枚举这个特性。我们看一看具体的使用。
/**
* 服务器响应码
*/
public enum ResponseCode { SUCCESS(200,"访问成功"),FAIL(404,"页面不存在"),ERROR(500,"服务器内部错误"); private Integer num;
private String desc; private ResponseCode(Integer num,String desc){
this.num = num;
this.desc = desc;
} public Integer getNum() {
return num;
} public String getDesc() {
return desc;
} /*
* 通过返回码得到枚举对象
*/
public static ResponseCode getByNum(Integer num){
for(ResponseCode code : values()){
if(code.getNum().equals(num)){
return code;
}
}
return null;
}
}
=============测试=====================
public static void main(String[] args) {
ResponseCode code = ResponseCode.getByNum(200);
switch (code) {
case SUCCESS:
System.out.println("成功");
break; default:
break;
}
}
在我做过的项目中,只有一处用到过枚举,用来记录字典的值,比方说,我写一个工具类,记录项目中使用到的所有字典相关数据。形如这样
public class Keys {
enum Sex{
MALE,FEMALE;
}
enum State{
SUCCESS,FAIL;
}
enum Month{
}
enum Week{
}
public static void main(String[] args) {
Keys.Sex.MALE.name();
}
}
但是在后面发现,还有更好用的配置字典的方式,创建一个字典类,将所有的字典数据放在一张表中,我们使用字典类来操作,这样要比上面使用枚举要好。
浅谈 Java 中的枚举的更多相关文章
- 浅谈java中的枚举类型(转)
用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- 浅谈Java中的equals和==
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 【转】浅谈Java中的hashcode方法(这个demo可以多看看)
浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...
- 浅谈Java中的final关键字
浅谈Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...
- 【转】浅谈Java中的hashcode方法
哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...
随机推荐
- Asp.Net使用加密cookie代替session验证用户登录状态 源码分享
首先 session 和 cache 拥有各自的优势而存在. 他们的优劣就不在这里讨论了. 本实例仅存储用户id于用户名,对于多级权限的架构,可以自行修改增加权限字段 本实例采用vs2010编写 ...
- [OI]省选前模板整理
省选前把板子整理一遍,如果发现有脑抽写错的情况,欢迎各位神犇打脸 :) 数学知识 数论: //组合数 //C(n,m) 在n个数中选m个的方案数 ll C[N][N]; void get_C(int ...
- backup服务器之rsync服务
backup服务器之rsync服务 rsync是开源的.快速的.多功能的可实现全量及增量的本地或远程数据同步备份的优秀工具.它拥有scp.cp的全量复制功能,同时比scp.cp命令更优秀.更强大. ...
- C++ 和 MFC的学习
1. 在Windows应用程序设计中,既可以使用个C的基本数据类型,也可以使用Windows自定义的数据类型.但要注意,凡是Windows自定义的关键字都要大写. 2. 什么是句柄? 在Windows ...
- mysql远程连接数据库
配置mysql允许远程连接的方法. (1)查看3306端口状态 netstat -an | grep 3306 (2)修改mysql配置文件 ubuntu系统:vim /etc/mysql/mysql ...
- MySQL分布式集群之MyCAT(三)rule的分析【转】
首先写在最前面,MyCAT1.4的alpha版本已经发布了,这里面修复了不少的bug,也完善了一细节,之前两篇博客已经做了一些修改 ---------------------------------- ...
- drop out为什么能够防止过拟合
来源知乎: dropout 的过程好像很奇怪,为什么说它可以解决过拟合呢?(正则化) 取平均的作用: 先回到正常的模型(没有dropout),我们用相同的训练数据去训练5个不同的神经网络,一般会得到5 ...
- web性能优化之js图片懒加载
html <div class="container"> <ul> <li> <div id="first" clas ...
- MySQL基础 - 视图
创建视图: 假设要将posts表的前十条数据作为视图 mysql> CREATE VIEW view_test AS SELECT * FROM POSTS LIMIT 10; 使用: 可以把视 ...
- (四)Jsoup 获取 DOM 元素属性值
第一节: Jsoup 获取 DOM 元素属性值 Jsoup获取DOM元素属性值 比如我们要获取博客的href属性值: 我们这时候就要用到Jsoup来获取属性的值 : 我们给下示例代码: package ...