在实习过程中,公司项目上用到枚举来表示请求处理的状态,返回结果,而自己以前也只是有简单的做过几个Demo,没有经常使用,所以当时使用的时候也是比较生疏。因此想找时间把这个枚举系统的复习整理一遍,方便以后查阅。
一、定义
枚举类型是指一组固定的常量组成合法的类型。Java中由关键字enum来定义一个枚举类型。
public enum Season {
SPRING(1,"春天"),
SUMMER(2,"夏天"),
AUTUMN(3,"秋天"),
WINER(4,"冬天");
}
二、特点
- 使用关键字enum
- 一串允许的值
- 可以单独定义在一个文件中,也可以嵌在其他java类中
- 枚举可以实现一个或者多个接口
- 可以定义新的变量
- 可以定义新的方法
- 可以定义根据具体枚举值而相异的类
三、常用的用法
用法一:声明常量
public enum Season {
SPRING,SUMMER,AUTUMN,WINER;
}
用法二:与switch搭配使用
public void change(Season season) {
switch (season) {
case SPRING:
System.out.println("春天来了!");
break;
case SUMMER:
System.out.println("夏天来了!");
break;
case AUTUMN:
System.out.println("秋天来了!");
break;
case WINER:
System.out.println("冬天来了!");
break;
default:
System.out.println("不知道什么季节呢!");
break;
}
}
用法三:在枚举中添加新的方法
/**
* 根据传入的code值获取对应的季节
*/
public Season getSeasonByCode(int code){
for(Season s : Season.values()){
if(s.getCode() == code){
return s;
}
}
return null;
}
用法四:实现接口,根据具体枚举值而生成相异的类
这种用法是以前自己没有使用过的,十分推荐。
public interface Behaviour {
void print();
String sayHello();
}
public enum Season implements Behaviour {
SPRING(1, "春天") {
@Override
public void print() {
System.out.println("春天来了!");
}
@Override
public String sayHello() {
return "春天";
}
},
SUMMER(2, "夏天") {
@Override
public void print() {
System.out.println("夏天来了!");
}
@Override
public String sayHello() {
return "夏天";
}
},
AUTUMN(3, "秋天") {
@Override
public void print() {
System.out.println("秋天来了!");
}
@Override
public String sayHello() {
return "秋天";
}
},
WINER(4, "冬天") {
@Override
public void print() {
System.out.println("冬天来了!");
}
@Override
public String sayHello() {
return "冬天";
}
};
//其他代码省略
这种方式可以用来优化代码中的if/else判断,调用的时候也十分简单。
public String judge(String name){
return Season.valueOf(name).sayHello();
}
三、深入探讨Java枚举
枚举是如何保证线程安全的
要探讨这个问题,首先我们必须先定义一个枚举
public enum t {
SPRING,SUMMER,AUTUMN,WINTER;
}
反编译后的代码
public final class T extends Enum
{
private T(String s, int i)
{
super(s, i);
}
public static T[] values()
{
T at[];
int i;
T at1[];
System.arraycopy(at = ENUM$VALUES, 0, at1 = new T[i = at.length], 0, i);
return at1;
}
public static T valueOf(String s)
{
return (T)Enum.valueOf(demo/T, s);
}
public static final T SPRING;
public static final T SUMMER;
public static final T AUTUMN;
public static final T WINTER;
private static final T ENUM$VALUES[];
static
{
SPRING = new T("SPRING", 0);
SUMMER = new T("SUMMER", 1);
AUTUMN = new T("AUTUMN", 2);
WINTER = new T("WINTER", 3);
ENUM$VALUES = (new T[] {
SPRING, SUMMER, AUTUMN, WINTER
});
}
}
接下来,我们就来分析一下反编译后的这些代码,来分析枚举是如何保证线程安全性问题的。
首先在public final class T extends Enum中,我们可以看到T是继承Enum,而且被final修饰的,所以T不能被其他类继承。当我们使用enum来定义一个枚举时,编译器会帮我们创建一个final类型的类继承于Enum,所以枚举类型不能被继承。 其次,我们可以看到SPRING,SUMMER,AUTUMN,WINTER都被static和final两个关键字修饰,属于静态的且不可变的变量,而且用了静态代码块来初始化这四个变量,使用static修饰和使用静态代码块来初始化说明什么?
有了解过Java类的加载机制的朋友会知道,static类型的属性会在类被加载之后被初始化,当一个Java类第一次被真正使用到的时候静态资源被初始化,Java类的加载和初始化过程都是线程安全的。所以,创建一个enum类型是线程安全的。
结语
文章部分内容转载H神的博客,十分推荐他写的文章!其他详细深入的内容请看原文。 www.hollischuang.com/archives/19…