Java 枚举
枚举 enum
什么是枚举类:
Java 枚举是一个特殊的类,一般表示一组常量
- 比如: 一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等…
- 类似这种当一个变量有几种固定可能的取值时, 可以将它定义为枚举类型
出现:
- Java1.5 之前是没有
枚举
和注解
的. - 那时候一般用接口常量来替代
而使用 Java 枚举类型 enum 可以更贴近地表示这种常量.
还可以配合 Switch使用…
枚举类的实现:
- JDK1.5 之前需要自定义枚举类.
- JDK 1.5 新增的
enum
关键字用于定义枚举类. - 若枚举只有一个对象, 则可以作为一种单例模式的实现方式.
1.5之前 自定义实现枚举类:
- 私有化类的构造器,保证不能在类的外部创建其对象
- 在类的内部创建枚举类的实例,声明为:
public static final
确保对象不会更改~ - 对象如果有实例变量,应该声明为:
private final
通过构造器初始化
SeasonTest1.Java
Season.Java
package com.wsm;
/**
* 自定义枚举类学习 Season季节: 一年有四个季节是固定是刚好用来做枚举类
*/
public class SeasonTest1 {
public static void main(String[] args) {
//春天
Season chu = Season.SPRING;
System.out.println(chu.toString());
/**
* ok,这就是自定义枚举类, 类的对象是有固定个数的!且不可更改, 救像一种规则固定的对象...
* 常用于规则状态的定义: 商品: 缺货 代发货 待付款...等固定的状态;
* */
}
}
class Season{
//1.私有化类的构造器,并给对象属性赋值: 如果有对象属性的话顺便给属性赋值~
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//2.声明Season对象的属性:private final修饰,因为枚举对象是固定的不能更改的.
private final String seasonName;
private final String seasonDesc;
//3.创建当前类的 固定数量的对象(一年四季): public static final的
//因为是私有的构造函数,类中进行创建... 如果枚举类只有一个对象,则就是一种单例模式! `饿汉式`
public static final Season SPRING = new Season("春天","春暖花开");
public static final Season SUMMER = new Season("夏天","夏日炎炎");
public static final Season AUTUMN = new Season("秋天","秋高气爽");
public static final Season WINTER = new Season("冬天","冰天雪地");
//ok,到这儿,自定义的枚举类就创建好了
//如果还有其它需求可以进行扩展... 创建方法:
/** 获取枚举类对象的属性 */
/** 常量只有get(); 方法 */
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
/** toString()方法 */
@Override
public String toString() {
return "Season{"
"seasonName='" seasonName '''
", seasonDesc='" seasonDesc '''
'}';
}
}
- JDK5 之前, 的枚举类需要通过改方法进行自定义~
Java中被 Final修饰的变量的几种赋值方式
- Final 表示"最后的、最终的"含义,变量一旦赋值后,不能被重新赋值
- 被 Final 修饰的实例变量必须显式指定初始值
- Final 修饰符通常和 static 修饰符一起使用来创建类常量
**非静态Final赋值有三种:**定义初始化、非静态代码块、构造方法
代码语言:javascript复制/*定义初始化时进行赋值
在声明对象时直接赋值,赋值后就不可变了,这种是最容易想到的
*/
public class FinalTest {
private final Integer num = 10;
}
/*代码块中赋值
这种是在定义之初不进行赋值操作,而是在代码块中进行赋值,也是可以的
构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行.
*/
public class FinalTest {
private final Integer num;
{
num = 10;
}
}
/*
构造器中赋值
在创建对象时进行赋值,一旦对象创建完成,就不可变了,所以在创建完对象后set()方法是不能进行赋值的
*/
public class FinalTest {
private final Integer num;
public FinalTest(Integer num) {
this.num = num;
}
}
静态使用Final: static final
- static final赋值有两种: 定义初始化、静态代码块
/* 定义初始化 */
public class FinalTest {
private static final Integer num = 10 ;
}
/* 静态代码块
用static{}包裹起来的代码片段,只会执行一次 静态代码块优先于构造块执行.
*/
public class FinalTest {
private static final Integer num;
static {
num = 10;
}
}
enum 关键字实现枚举类:
- enum 定义的枚举类默认继承了
Java.lang.Enum
类:因此不能再 extends 继承其他类
但可以 implements - 枚举类的构造器只能使用 private 权限修饰符
必须在枚举类的第一行声明枚举类对象
JDK 1.5 中可以在 switch 表达式中使用Enum定义的枚举类的对象 作为表达式
case 子句可以直接使用枚举值的名字(无需添加枚举类作为限定)
SeasonTest2.Java
Season.Java
package com.wsm.two;
import javax.sound.midi.Soundbank;
/***
* JDK1.5 新增enum
*/
public class SeasonTest2 {
public static void main(String[] args) {
/** 秋天 */
Season AUTUMN = Season.AUTUMN;
System.out.println(AUTUMN); //尝试注释 toString()方法输出: AUTUMN (对象名)
//enum extends Java.lang.enum类
/** enum常用方法 */
//values()方法:
// 返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值
//valueOf(String str)
// 可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException。
//toString() 返回当前枚举类对象常量的名称
/** values() */
System.out.println("enum常用方法values()");
Season[] values = Season.values(); //返回该enum 的所有对象
//遍历结果集
for (Season value : values) {
System.out.println(value);
}
/** valueOf(String str) */
System.out.println("enum常用方法valueOf(String str)");
Season winter = Season.valueOf("WINTER"); //根据固定对象名,返回对应的enum
System.out.println(winter);
/** switch用法
* 判断对象属于那一个...
* */
System.out.println("enum switch用法");
switch (winter){
case SPRING:
System.out.println("春");
break;
case SUMMER:
System.out.println("夏");
break;
case AUTUMN:
System.out.println("秋");
break;
case WINTER:
System.out.println("冬");
break;
default:
System.out.println("没有匹配!");
}
}
}
/** 可以于自定义枚举进行比较查看~ */
enum Season{
//1.必须在枚举类的第一行声明枚举类对象
//枚举类的所有实例必须在枚举类中显式列出(, 分隔 ; 结尾)
//因为枚举,本机不可修改由类访问可以取消: public static final 类
// public static final Season SPRING = new Season("春天","春暖花开");
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","冰天雪地");
//2.声明Season对象的属性:private final修饰
private final String seasonName;
private final String seasonDesc;
//3.私有化类的构造器,并给对象属性赋值
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//扩展方法
/** get */
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
/** toString
* 注释方法直接输出发现,即使不重新toString(); 也不是打印对象的: 地址值(栈指向堆的地址!)
* 因为: enum类,是继承于 Java.lang.enum的,而不是 Object类
* */
// @Override
// public String toString() {
// return "Season{"
// "seasonName='" seasonName '''
// ", seasonDesc='" seasonDesc '''
// '}';
// }
}
enum 常用方法
方法名称 | 描述 |
---|---|
values() | 以数组形式返回枚举类型的所有成员 |
valueOf( String ) | 将普通字符串转换为枚举实例 |
compareTo() | 比较两个枚举成员在定义时的顺序 |
ordinal() | 获取枚举成员的索引位置 |
enum 高级:implements实现类
- enum 类继承了
java.lang.enum类
Java单根性所以不能在继承, 但Java 可以多实现
-
eunm 类 还可以 实现接口...达到扩展的方式
实现方式:
正常实现,重写方法… 但这样所有的对象, 方法实现都一样!
SeasonTest3
Season
Info
代码语言:javascript复制public class SeasonTest3 {
public static void main(String[] args) {
Season autumn = Season.AUTUMN;
autumn.show();
}
}
//使用enum关键字枚举类 implements 实现接口,重写show()方法~
enum Season implements Info{
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","冰天雪地");
//2.声明Season对象的属性:private final修饰
private final String seasonName;
private final String seasonDesc;
//3.私有化类的构造器,并给对象属性赋值
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//重写接口的方法!
@Override
public void show() {
System.out.println("这是一个季节~");
}
}
/** 接口 */
interface Info{
void show();
}
给每个enum 对象,来一个特有的固定实现!
代码语言:javascript复制public class SeasonTest4 {
public static void main(String[] args) {
Season autumn = Season.AUTUMN;
autumn.show();
}
}
//使用enum关键字枚举类 implements 实现接口,重写show()方法~
enum Season implements Info {
SPRING("春天","春暖花开"){
@Override
public void show() { System.out.println("春天在哪里?"); }
},
SUMMER("夏天","夏日炎炎"){
@Override
public void show() { System.out.println("宁夏"); }
},
AUTUMN("秋天","秋高气爽"){
@Override
public void show() { System.out.println("秋天不回来"); }
},
WINTER("冬天","冰天雪地"){
@Override
public void show() { System.out.println("大约在冬季"); }
};
//2.声明Season对象的属性:private final修饰
private final String seasonName;
private final String seasonDesc;
//3.私有化类的构造器,并给对象属性赋值
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
}
/** 接口 */
interface Info{
void show();
}
枚举集合
在 Java 语言中和枚举类相关的,还有两个枚举集合类 java.util.EnumSet
和 java.util.EnumMap
使用 EnumSet
可以保证元素不重复,并且能获取指定范围内的元素
public class EnumTest {
public static void main(String[] args) {
List<ErrorCodeEnum> list = new ArrayList<ErrorCodeEnum>();
list.add(ErrorCodeEnum.SUCCESS);
list.add(ErrorCodeEnum.SUCCESS); //重复元素
list.add(ErrorCodeEnum.SYS_ERROR);
list.add(ErrorCodeEnum.NAMESPACE_NOT_FOUND);
// 去掉重复数据
EnumSet<ErrorCodeEnum> enumSet = EnumSet.copyOf(list);
System.out.println("去重:" enumSet);
// 获取指定范围的枚举(获取所有的失败状态)
EnumSet<ErrorCodeEnum> errorCodeEnums = EnumSet.range(ErrorCodeEnum.ERROR, ErrorCodeEnum.UNKNOWN_ERROR);
System.out.println("所有失败状态:" errorCodeEnums);
}
}
enum ErrorCodeEnum {
SUCCESS(1000, "success"),
ERROR(2001, "parameter error"),
SYS_ERROR(2002, "system error"),
NAMESPACE_NOT_FOUND(2003, "namespace not found"),
NODE_NOT_EXIST(3002, "node not exist"),
NODE_ALREADY_EXIST(3003, "node already exist"),
UNKNOWN_ERROR(9999, "unknown error");
private int code;
private String msg;
ErrorCodeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int code() { return code; }
public String msg() { return msg; }
}
EnumMap
与 HashMap
类似,不过它是一个专门为枚举设计的 Map
集合
相比 HashMap
来说它的性能更高,因为它内部放弃使用链表和红黑树的结构,采用数组作为数据存储的结构
以枚举作为 key,查询直接找到对应的 数组下标
快速定位元素
EnumMap<枚举对象,Object>