一文了解java枚举
1. 枚举的由来
当我们知道所有变量的可能性时,尽量使用枚举类型来定义,比如季节,春夏秋冬,一周(一二三四五六七),只读不需要修改
有限的一个一个列举出来的类叫做枚举类,枚举是一组常量的集合,枚举也是一个特殊的类,里面包含了一组有限的特定对象
2. 自定义实现枚举
- 不需要提供set方法,因为枚举对象值不能被修改(这里注意枚举一般只用于知道所有固定变量的值)
- 构造器私有化
- 枚举对象/属性用" final static""修饰
- 根据不同的类,生成不同数量的枚举对象,而且枚举对象定义全部大写
引用前例子
这里已知季节的所有变量是固定的春夏秋冬,可以用枚举来写
package EG.枚举的由来;
//设置季节,春夏秋冬
public class Test {
public static void main(String[] args) {
/*
* 秋autumn
* 冬winter
* */
Season spring = new Season("春天","暖和");
Season summer = new Season("夏天","酷热");
Season autumn = new Season("秋天", "凉爽至极");
Season winter = new Season("冬天", "冰冷刺骨");
System.out.println(spring);
}
}
package EG.枚举的由来;
/**
* @author 简水君
*/
public class Season {
/** 季节的名称*/
private String name;
/** 季节的信息*/
private String desc;
//javaBean
public Season() {
}
public Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return name+"的特点: "+desc;
}
}
引用后例子
package EG.枚举的由来.引用后;
//设置季节,春夏秋冬
public class Test {
public static void main(String[] args) {
System.out.println(Season.SPRING);
System.out.println(Season.SUMMER);
System.out.println(Season.SPRING);
System.out.println(Season.WINTER);
}
}
这里模拟Season类继承enum类称为枚举类,其次是季节都是固定的值,不能再次创建也不能修改,将构造器私有化,把set方法删除,创建静态对象
package EG.枚举的由来.引用后;
/**
* @author 简水君
*/
public class Season {
/**
* 季节的名称
*/
private String name;
/**
* 季节的信息
*/
private String desc;
//javaBean
/** 这里模拟Season类继承enum类称为枚举类 */
public final static Season SPRING = new Season("春天", "暖和");
public final static Season SUMMER = new Season("夏天", "酷热");
public final static Season AUTUMN = new Season("秋天", "凉爽至极");
public final static Season WINTER = new Season("冬天", "冰冷刺骨");
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return name + "的特点: " + desc;
}
}
3.枚举的使用
定义枚举用名词enum
,第一行只能是常量(最终静态/类的对象的缩写),多个常量用逗号分隔,后面行随意
格式:
- 无参时:
变量名1,变量名2,变量名3;
等价于变量n()
- 有参时;
变量名1(实参),变量名2(实参),变量名3(实参);
package EG.b枚举的使用;
/**
* @author 简水君
*/
//设置季节,春夏秋冬
public class Test {
public static void main(String[] args) {
System.out.println(Season.SPRING);
System.out.println(Season.SUMMER);
System.out.println(Season.SPRING);
System.out.println(Season.WINTER);
}
}
enum Season {
//这里季节都是固定的值把set方法删除
/* 这里 SPRING("春天", "暖和")相当于 public final static Season SPRING = new Season("春天", "暖和"); 假设有个无参常量 SPRING,也是等价于SPRING()的*/
SPRING("春天", "暖和"),SUMMER("夏天", "酷热"),AUTUMN("秋天", "凉爽至极"),WINTER("冬天", "冰冷刺骨");
//javaBean
/**
* 季节的名称
*/
private String name;
/**
* 季节的信息
*/
private String desc;
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return name + "的特点: " + desc;
}
}
4.反编译enum类
这里 底层将该季节类Season为最终类,不能被继承且继承了Enum接口,有其方法values(),valueOf(),还有一个静态代码块
练习题
这里BOY,GIRL都是创建了无参的常量对象,这里输出boy指的是Boy的对象(类加载时加载一次静态最终常量),但这里没有重写Enum的toString()方法,所以指的是其常量名字,两个引用指向一个对象
5.枚举enum的方法
package EG.c枚举方法的使用;
import java.util.Arrays;
/**
* @author 简水君
*/
public class Test {
public static void main(String[] args) {
Season sp = Season.SPRING;
// 1. toString()这里返回的是枚举对象的名字 SPRING System.out.println(sp);
// 2. name()这里返回的也是枚举对象的名字 SPRING System.out.println(sp.name());
// 3.返回的是枚举对象的索引位置 0 , 可以用于comparable比较
System.out.println(sp.ordinal());
// 4. values() 这里返回的是一个枚举的所有常量的数组
Season[] values = Season.values();
System.out.println(Arrays.toString(values));
// for( Season s : values ){}
// 5. valueOf(" ")获取包含字符串的常量对象
Season sa = Season.valueOf("WINTER");
System.out.println(sa);
// 6.CompareTo: 比较两个枚举常量,比较的是编号的差值,底层是两者调用ordinal方法的差值,这可以算出两个常量位置的差值
//春天和冬天的差值0-3
int i = Season.SPRING.compareTo(Season.WINTER);
System.out.println(i);
}
}
enum Season {
SPRING("春天", "暖和"), SUMMER("夏天", "酷热"), AUTUMN("秋天", "凉爽至极"), WINTER("冬天", "冰冷刺骨");
private String name;
private String desc;
private Season() {
}
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
}
例子
package EG.d练习题;
import java.util.Arrays;
import java.util.PropertyResourceBundle;
/**
* @author 简水君
*/
public class Test {
public static void main(String[] args) {
//获取所有的常量数组,遍历
Week[] values = Week.values();
System.out.println("所有星期信息如下: ");
for (Week value : values) {
System.out.print(value+" ");
}
}
}
/**
因为我们知道一周所有变量固定的值,所以用枚举来写,而且各个变量不给改变,
而且定义的Week的是最终类,不给继承,但可以创建对象
*/
enum Week{
MONDAY("周一"),TUESDAY("周二"),WEDNESDAY("周三"),THURSDAY("周四"),FRIDAY("周五"),SATURDAY("周六"),SUNDAY("周末");
private String name;
private Week() {
}
private Week(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
6.枚举实现接口
- 使用enum关键字后,就不能再继承其他类了,但enum定义的类底层会继承Enum接口,这算是java的单继承机制了
- 枚举类和普通类一样,可以实现接口,如下形式
enum 类名 implements 接口1,接口2{}
,多几个义父
package EG.e枚举实现接口;
public class Test {
public static void main(String[] args) {
// 调用枚举的方法
Music.GUANGHUISUIYUE.play();
}
}
enum Music implements Play{
//定义一个音乐对象
GUANGHUISUIYUE;
@Override
public void play() {
//打印常量的名称
System.out.println("正在播放🎵: "+Music.GUANGHUISUIYUE.name());
}
}
interface Play{
void play();
}
7.枚举的特点
- 枚举的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象
- 枚举都是final修饰的最终类,不能被继承的,且不能创建对象
- 枚举类中,第二行开始,可以定义类的其他各种成员
- 枚举类都是继承的java.lang.Enum 的方法
- 枚举变量 = spring("春天","暖和") ,Season spring = new Season("春天","暖和");
8.为什么说枚举常量是一个单例设计模式
因为 枚举常量是最终的final修饰的 ,不可改变的,只能创建一次 .通过使用枚举来定义常量集合,可以确保常量的唯一性和不可变性。
由于枚举常量在编译时就被创建并且在运行时只有一个实例,所以可以避免多线程并发访问下导致的线程安全问题。
9.枚举作为限制传值
这里对于provideInfo(),只能传BOY/Girl
当你的才华配不上你的野心,努力的时候到了!