对象
是有限的、固定的几个,不能让用户随意创建。星期
:Monday(星期一)…Sunday(星期天)性别
:Man(男)、Woman(女)月份
:January(1月)…December(12月)季节
:Spring(春节)…Winter(冬天)三原色
:red(红色)、green(绿色)、blue(蓝色)支付方式
:Cash(现金)、WeChatPay(微信)、Alipay(支付宝)、BankCard(银行卡)、CreditCard(信用卡)就职状态
:Busy(忙碌)、Free(空闲)、Vocation(休假)、Dimission(离职)订单状态
:Nonpayment(未付款)、Paid(已付款)、Fulfilled(已配货)、Delivered(已发货)、Checked(已确认收货)、Return(退货)、Exchange(换货)、Cancel(取消)线程状态
:创建、就绪、运行、阻塞、死亡enum
关键字来快速定义枚举类型。① 开发中,如果针对于某个类,其实例(对象)是确定个数的。则推荐将此类声明为枚举类。
② 如果枚举类的实例只有一个,则可以看做是单例的实现方式。
在JDK5.0之前如何声明枚举类呢?手动定义枚举类,通过class的方式定义枚举类。
私有化
类的构造器,保证不能在类的外部创建其对象public static final
,对外暴露这些常量对象实例变量
,应该声明为private final
(建议,不是必须),并在构造器中初始化季节
:Spring(春节)…Winter(冬天)
将Season定义为“枚举类”。
public class SeasonTest {
}
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
}
分析
<1> 限制构造器
Season是枚举类,它的对象个数是确定的,所以先搞定构造器的问题,若是构造器对外暴露,那么外面就可以随意创建对象了。
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//1.私有化类的构造器
private Season(){
}
}
<2> 声明当前类的对象的实例变量
前面讲单例的时候,没有提供关于对象的实例变量,这里提供一下。
比如季节要造四个对象,每个季节对象都有一个或者两个实例的变量,就先在前面声明一下。
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//声明当前类的对象的实例变量
String seasonName; //季节名称
String seasonDesc; //季节描述
//1.私有化类的构造器
private Season(){
}
}
这里定义了两个实例变量,再给这两个实例变量一些修饰。
比如造对象的时候,就将属性赋值了,只让外面获取值而不能修改值(final
)。
而且获取是通过方法来获得,所以这两个变量要私有化(private
)。
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//声明当前类的对象的实例变量
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//1.私有化类的构造器
private Season(){
}
}
注意不能加static,加了static就表示它们都共用了,显然这里不能共用。
上面声明完之后,因为是final
的,所以要对应“显示初始化”或者“构造器”或者“代码块”来给它赋值。
这里咱们选择在构造器中将它初始化。
如下:
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//2.声明当前类的对象的实例变量
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//1.私有化类的构造器
private Season(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
}
如果针对当前类的多个实例,要是有实例变量的话,就给它声明一下,一定要注意它的修饰。
<3> 提供实例变量的get方法
既然上面提供了相应的属性并私有化了,那如果外部想看一下具体对象的值的话,这里就需要提供相应的get方法。
如下:
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//3. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
<4> 创建当前类的实例
接下来在类的内部创建对象。
如下:
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//4.创建当前类的实例
Season spring=new Season("春天","春暖花开");
Season summer=new Season("夏天","夏日炎炎"); //Ctrl+D可以快速复制上一行的代码
Season autumn=new Season("秋天","秋高气爽");
Season winter=new Season("冬天","白雪皑皑");
}
有几个注意点。
①这几个对象在类的外部可以使用,但是不能够修改。
使用的话,在类的外部直接调用,没必要再通过方法了(不再提供对象的get方法)。
所以这里直接就可以public
。比如:public Season spring=new Season("春天","春暖花开");
②此时spring是当前类的一个对象,在外面需要拿类去调用。
而现在它不是静态的,得拿对象来调,但此时它就是一个对象啊。目的是为了拿到它,现在还要用它去调,这就矛盾了。
所以此时这个对象还要加一个static
,这样就可以直接在类的外部用类来调用。
比如:public static Season spring=new Season("春天","春暖花开");
③现在还有一个问题,这个对象可以使用,但是不能更改。
虽然这里外部看不到构造器,如下:
但是也不能更改为null:
既然不能让它更改,那么还需要final
一下,比如:public static final Season spring=new Season("春天","春暖花开");
所以最终这些实例都需要这样来修饰:public static final
如下:
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//4.创建当前类的实例
public static final Season spring=new Season("春天","春暖花开");
public static final Season summer=new Season("夏天","夏日炎炎"); //Ctrl+D可以快速复制上一行的代码
public static final Season autumn=new Season("秋天","秋高气爽");
public static final Season winter=new Season("冬天","白雪皑皑");
}
可以看到,刚才的地方就会报错了:
既然这里是全局常量
了,那么大写比较合适,如下:
//4.创建当前类的实例
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("冬天","白雪皑皑");
最后,还可以提供一个toString
方法,方便在调用对象的时候看一看相应属性的值。
//toString方法
@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
所以,jdk5.0之前枚举类就是这样写的:
代码
package yuyi02;
/**
* ClassName: SeasonTest
* Package: yuyi02
* Description:
*
* @Author 雨翼轻尘
* @Create 2023/12/3 0003 8:57
*/
public class SeasonTest {
public static void main(String[] args) {
System.out.println(Season.SPRING); //打印
System.out.println(Season.SUMMER.getSeasonName());
System.out.println(Season.SUMMER.getSeasonDesc());
}
}
//jdk5.0之前定义枚举类的方式
class Season{ //这个类的对象个数是有限个的
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//1.私有化类的构造器
private Season(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//3. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//4.创建当前类的实例,需要使用 public static final修饰
public static final Season SPRING=new Season("春天","春暖花开");
public static final Season SUMMER=new Season("夏天","夏日炎炎"); //Ctrl+D可以快速复制上一行的代码
public static final Season AUTUMN=new Season("秋天","秋高气爽");
public static final Season WINTER=new Season("冬天","白雪皑皑");
//toString方法
@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
输出结果
格式
【修饰符】 enum 枚举类名{
常量对象列表
}
【修饰符】 enum 枚举类名{
常量对象列表;
对象的实例变量列表;
}
举例1:
package com.atguigu.enumeration;
public enum Week {
MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}
public class TestEnum {
public static void main(String[] args) {
Season spring = Season.SPRING;
System.out.println(spring);
}
}
在idea里面新建java文件,可以看到有一个Enum
:
这里为了方便演示,都写在一个文件里面了。
public class SeasonTest1 {
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1{
}
如果按照刚才jdk5.0之前的写法,应该是这样:
enum Season1{
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//1.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//3. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//4.创建当前类的实例,需要使用 public static final修饰
public static final Season1 SPRING=new Season1("春天","春暖花开");
public static final Season1 SUMMER=new Season1("夏天","夏日炎炎"); //Ctrl+D可以快速复制上一行的代码
public static final Season1 AUTUMN=new Season1("秋天","秋高气爽");
public static final Season1 WINTER=new Season1("冬天","白雪皑皑");
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
编译器会报错。
对于enum
关键字来定义的枚举类有一个要求,一上来就必须要将对象放在这。
那就将第4步挪到前面来,哎?错误更多了:
这里需要做一个调整。
以前说过“接口”,接口里面有抽象方法,抽象方法都声明为public abstract
,当时说这两个关键字可以省略不写。
而对于枚举类来说,之前说过实例它们都是用public static final
来声明的。
所以需要将相同的部分去除。(注意不是可以去掉,而是必须去除)
同样,对象也都是Season1
类型,也要去掉。
后面new Season1
也一样,去掉。(new的是具体的类的构造器,所以可以去除)
对象名不一样,所以不要删。
小括号也不要去除,因为里面有变量,相当于对形参赋值了,需要括一下。
下面红框部分都是要去除的:(等于号也删掉)
删完之后:
SPRING("春天","春暖花开");
SUMMER("夏天","夏日炎炎");
AUTUMN("秋天","秋高气爽");
WINTER("冬天","白雪皑皑");
还要改一个地方,多个对象之间要用逗号隔开,最后分号结束。
所以,最终结果:
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
构造器,实例变量,get方法该有还是要有。
代码
//jdk5.0中使用enum关键字定义枚举类
enum Season1{
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
刚才写的例子中,枚举类Season1
其实有一个默认父类。
比如我们可以获取一下当前对象所属的类及父类。
如下:
public class SeasonTest1 {
public static void main(String[] args) {
System.out.println(Season1.SPRING.getClass()); //获取当前对象所属的类
System.out.println(Season1.SPRING.getClass().getSuperclass()); //获取当前对象所属类的父类
}
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1{
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
输出结果:
所以,当前类有一个默认父类Enum
。
如果此时想让枚举类去继承其他类,是不可以的。
如下:
用enum关键字定义的枚举类,默认的父类已经确定好了,不要让它再去继承其他类了。
如果感兴趣,还可以看一下Enum类的父类,是Object,如下:
既然枚举类都继承于Enum类,在Enum类中提供了一些方法,这里看一下它里面的方法都有哪些。
String toString(): 默认返回的是常量名(对象名),可以继续手动重写该方法!
static 枚举类型[] values():返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法
static 枚举类型 valueOf(String name):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException。
String name():得到当前枚举常量的名称。建议优先使用toString()。
int ordinal():返回当前枚举常量的次序号,默认从0开始
String toString()
: 默认返回的是常量名(对象名),可以继续手动重写该方法!
//1.toString():没有重写的时候打印当前对象的名称,重写的话打印的就是重写之后的
System.out.println(Season1.SPRING);
代码
public class SeasonTest1 {
public static void main(String[] args) {
//测试方法
//1.toString()
System.out.println(Season1.SPRING);
}
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 {
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
输出结果
可以发现,它默认打印当前对象的名字。
如果不想让它这样打印,可以重写一下。
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
然后再去Run,就是重写之后的了:
toString():没有重写的时候打印当前对象的名称,重写的话打印的就是重写之后的
String name()
:得到当前枚举常量的名称。建议优先使用toString()。
//2.name():打印当前对象的名称
System.out.println(Season1.SPRING.name());
代码
public class SeasonTest1 {
public static void main(String[] args) {
//测试方法
//1.toString():没有重写的时候打印当前对象的名称,重写的话打印的就是重写之后的
System.out.println(Season1.SPRING);
//2.name():打印当前对象的名称
System.out.println(Season1.SPRING.name());
}
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 {
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
输出结果
name():打印当前对象的名称。
static 枚举类型[] values()
:返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法。
//3.values():将当前枚举类所有对象都取出来
Season1[] values=Season1.values(); //静态方法,返回值是一个数组,数组就是Season1类型的
代码
public class SeasonTest1 {
public static void main(String[] args) {
//测试方法
//1.toString():没有重写的时候打印当前对象的名称,重写的话打印的就是重写之后的
System.out.println(Season1.SPRING);
//2.name():打印当前对象的名称
System.out.println(Season1.SPRING.name());
//3.values():将当前枚举类所有对象都取出来
Season1[] values=Season1.values(); //静态方法,返回值是一个数组,数组就是Season1类型的
//输出数组元素
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]); //打印的时候会调用toSting方法
}
}
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 {
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
输出结果
values():将当前枚举类所有对象都取出来。想看当前枚举类有什么对象,就可以使用这个方法。
static 枚举类型 valueOf(String name)
:可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException。
//4.valuesOf(String objName):返回当前枚举类中名称为objName的枚举类对象,如果枚举类中不存在objName名称的对象,则报错
String objName="WINTER";
Season1 season1=Season1.valueOf(objName); //根据传进来的字符串,找到在枚举类中叫这个名字的枚举类的对象
System.out.println(season1);
代码
public class SeasonTest1 {
public static void main(String[] args) {
//测试方法
//1.toString():没有重写的时候打印当前对象的名称,重写的话打印的就是重写之后的
System.out.println(Season1.SPRING);
//2.name():打印当前对象的名称
System.out.println(Season1.SPRING.name());
//3.values():将当前枚举类所有对象都取出来
Season1[] values=Season1.values(); //静态方法,返回值是一个数组,数组就是Season1类型的
//输出数组元素
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]); //打印的时候会调用toSting方法
}
System.out.println(); //换行
//4.valuesOf(String objName):
String objName="WINTER";
Season1 season1=Season1.valueOf(objName); //根据传进来的字符串,找到在枚举类中叫这个名字的枚举类的对象
System.out.println(season1);
}
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 {
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
输出结果
若传进来的不是枚举类里面的值,就会报错,比如传进来了一个WINTER1,如下:
IllegalArgumentException
:非法参数异常。
int ordinal()
:返回当前枚举常量的次序号,默认从0开始。非静态方法,需要拿对象去调用。
//5.ordinal()
System.out.println(Season1.AUTUMN.ordinal()); //打印出当前对象在枚举类中是第几个声明的对象
代码
public class SeasonTest1 {
public static void main(String[] args) {
//测试方法
//1.toString():没有重写的时候打印当前对象的名称,重写的话打印的就是重写之后的
System.out.println(Season1.SPRING);
System.out.println(); //换行
//2.name():打印当前对象的名称
System.out.println(Season1.SPRING.name());
System.out.println(); //换行
//3.values():将当前枚举类所有对象都取出来
Season1[] values=Season1.values(); //静态方法,返回值是一个数组,数组就是Season1类型的
//输出数组元素
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]); //打印的时候会调用toSting方法
}
System.out.println(); //换行
//4.valuesOf(String objName):返回当前枚举类中名称为objName的枚举类对象,如果枚举类中不存在objName名称的对象,则报错
String objName="WINTER";
//String objName="WINTER1"; //IllegalArgumentException异常
Season1 season1=Season1.valueOf(objName); //根据传进来的字符串,找到在枚举类中叫这个名字的枚举类的对象
System.out.println(season1);
System.out.println(); //换行
//5.ordinal()
System.out.println(Season1.AUTUMN.ordinal()); //打印出当前对象在枚举类中是第几个声明的对象
}
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 {
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
输出结果
这几个方法重点关注values()–一共多少个,都是哪些枚举类对象和valuesOf–根据指定的名找到枚举类对象。
举例2:
public enum SeasonEnum {
SPRING("春天","春风又绿江南岸"),
SUMMER("夏天","映日荷花别样红"),
AUTUMN("秋天","秋水共长天一色"),
WINTER("冬天","窗含西岭千秋雪");
private final String seasonName;
private final String seasonDesc;
private SeasonEnum(String seasonName, String seasonDesc) {
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
举例3:
package com.atguigu.enumeration;
public enum Week {
MONDAY("星期一"),
TUESDAY("星期二"),
WEDNESDAY("星期三"),
THURSDAY("星期四"),
FRIDAY("星期五"),
SATURDAY("星期六"),
SUNDAY("星期日");
private final String description;
private Week(String description){
this.description = description;
}
@Override
public String toString() {
return super.toString() +":"+ description;
}
}
package com.atguigu.enumeration;
public class TestWeek {
public static void main(String[] args) {
Week week = Week.MONDAY;
System.out.println(week);
switch (week){
case MONDAY:
System.out.println("怀念周末,困意很浓");break;
case TUESDAY:
System.out.println("进入学习状态");break;
case WEDNESDAY:
System.out.println("死撑");break;
case THURSDAY:
System.out.println("小放松");break;
case FRIDAY:
System.out.println("又信心满满");break;
case SATURDAY:
System.out.println("开始盼周末,无心学习");break;
case SUNDAY:
System.out.println("一觉到下午");break;
}
}
}
经验之谈:
开发中,当需要定义一组常量时,强烈建议使用枚举类。
语法:
//1、枚举类可以像普通的类一样,实现接口,并且可以多个,但要求必须实现里面所有的抽象方法!
enum A implements 接口1,接口2{
//抽象方法的实现
}
//2、如果枚举类的常量可以继续重写抽象方法!
enum A implements 接口1,接口2{
常量名1(参数){
//抽象方法的实现或重写
},
常量名2(参数){
//抽象方法的实现或重写
},
//...
}
举例:
interface Info{
void show();
}
//使用enum关键字定义枚举类
enum Season1 implements Info{
//1. 创建枚举类中的对象,声明在enum枚举类的首位
SPRING("春天","春暖花开"){
public void show(){
System.out.println("春天在哪里?");
}
},
SUMMER("夏天","夏日炎炎"){
public void show(){
System.out.println("宁静的夏天");
}
},
AUTUMN("秋天","秋高气爽"){
public void show(){
System.out.println("秋天是用来分手的季节");
}
},
WINTER("冬天","白雪皑皑"){
public void show(){
System.out.println("2002年的第一场雪");
}
};
//2. 声明每个对象拥有的属性:private final修饰
private final String SEASON_NAME;
private final String SEASON_DESC;
//3. 私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.SEASON_NAME = seasonName;
this.SEASON_DESC = seasonDesc;
}
public String getSEASON_NAME() {
return SEASON_NAME;
}
public String getSEASON_DESC() {
return SEASON_DESC;
}
}
情况1:枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是同一个方法。
拿这个例子来说。
//jdk5.0中使用enum关键字定义枚举类
enum Season1 {
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
现在创建一个接口Info,在里面写一个抽象方法show()。
interface Info{
void show();
}
然后让枚举类Season1去实现接口Info,自然而然地需要将接口中地抽象方法重写一下(为了实例化)。
//jdk5.0中使用enum关键字定义枚举类
enum Season1 implements Info{
//...
@Override
public void show() {
System.out.println("这是一个季节");
}
}
OK了,show()
就是一个普通的方法,方法非静态,就可以在测试类SeasonTest1里面通过对象来调用它。
如下:
public class SeasonTest1 {
public static void main(String[] args) {
//通过枚举类的对象调用重写接口中的方法
Season1.SUMMER.show();
Season1.AUTUMN.show();
}
}
interface Info{
void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 implements Info{
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
@Override
public void show() {
System.out.println("这是一个季节");
}
}
输出结果:
情况2:让枚举类的每一个对象重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是不同的实现的方法。
既然结果不一样,其实就是让每一个对象,各自重写一下这个方法。
还是刚才的代码:
public class SeasonTest2 {
}
interface Info1{
void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season2 implements Info1{
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season2(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season2{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
@Override
public void show() {
System.out.println("这是一个季节");
}
}
枚举类Season2实现接口Info1。
此时我们不在当前类里面重写show()方法了,而是让每个对象各自去实现抽象方法。
在这里整一对大括号,如下:
然后在这一对大括号里面重写show()
方法,如下:
其他的也是类似:
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
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("冬天来了,银装素裹");
}
};
然后我们在main方法里面测试一下:
public class SeasonTest2 {
public static void main(String[] args) {
Season2[] values=Season2.values(); //将所有对象都拿到,然后存入数组values中
for (int i = 0; i < values.length; i++) {
values[i].show(); //用每个对象去调用show()方法,各自就调用各自重写的方法
}
}
}
interface Info1{
void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season2 implements Info1{
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
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.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season2(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season2{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
输出结果:
其实可以将它们看作是“匿名的实现类”,因为将方法show()单独重写了,其实都是继承于当前类Season2的匿名子类。
具体细节不用深究,只需要知道可以对每个对象单独重写即可。有一些特殊场景可能会用到。
枚举类区别于单例模式,就是它的对象不止一个,有几个造几个。
【SeasonTest1.java】
package yuyi02;
/**
* ClassName: SeasonTest1
* Package: yuyi02
* Description:
*
* @Author 雨翼轻尘
* @Create 2023/12/3 0003 10:03
*/
public class SeasonTest1 {
public static void main(String[] args) {
/*System.out.println(Season1.SPRING.getClass()); //获取当前对象所属的类
System.out.println(Season1.SPRING.getClass().getSuperclass()); //获取当前对象所属类的父类
System.out.println(Season1.SPRING.getClass().getSuperclass().getSuperclass()); //获取当前对象所属类的父类的父类*/
//测试方法
//1.toString():没有重写的时候打印当前对象的名称,重写的话打印的就是重写之后的
System.out.println(Season1.SPRING);
System.out.println(); //换行
//2.name():打印当前对象的名称
System.out.println(Season1.SPRING.name());
System.out.println(); //换行
//3.values():将当前枚举类所有对象都取出来
Season1[] values=Season1.values(); //静态方法,返回值是一个数组,数组就是Season1类型的
//输出数组元素
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]); //打印的时候会调用toSting方法
}
System.out.println(); //换行
//4.valuesOf(String objName):返回当前枚举类中名称为objName的枚举类对象,如果枚举类中不存在objName名称的对象,则报错
String objName="WINTER";
//String objName="WINTER1"; //IllegalArgumentException异常
Season1 season1=Season1.valueOf(objName); //根据传进来的字符串,找到在枚举类中叫这个名字的枚举类的对象
System.out.println(season1);
System.out.println(); //换行
//5.ordinal()
System.out.println(Season1.AUTUMN.ordinal()); //打印出当前对象在枚举类中是第几个声明的对象
System.out.println(); //换行
//通过枚举类的对象调用重写接口中的方法
Season1.SUMMER.show();
Season1.AUTUMN.show();
}
}
interface Info{
void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 implements Info{
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//2.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season1(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
@Override
public void show() {
System.out.println("这是一个季节");
}
}
输出结果
【SeasonTest2.java】
package yuyi05;
/**
* ClassName: SeasonTest2
* Package: yuyi05
* Description:
*
* @Author 雨翼轻尘
* @Create 2023/12/4 0004 14:37
*/
public class SeasonTest2 {
public static void main(String[] args) {
Season2[] values=Season2.values(); //将所有对象都拿到,然后存入数组values中
for (int i = 0; i < values.length; i++) {
values[i].show(); //用每个对象去调用show()方法,各自就调用各自重写的方法
}
}
}
interface Info1{
void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season2 implements Info1{
//1.必须在枚举类的开头声明多个对象,对象之间使用逗号隔开
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.声明当前类的对象的实例变量,需要使用 private final修饰
private final String seasonName; //季节名称
private final String seasonDesc; //季节描述
//3.私有化类的构造器
private Season2(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
//4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//toString方法
@Override
public String toString() {
return "Season2{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
输出结果
题目描述
员工就职状态
:Busy(忙碌)、Free(空闲)、Vocation(休假)、Dimission(离职)
☕分析
员工的状态Status
可以声明为枚举类,他有几种状态是确定的,不用在造Employee的时候再去new具体的Status了,就那几种状态,提前造好,直接拿来用即可。
上面我们举例的SeasonTest1中,枚举类Season1,每个季节都有两个实例变量,现在的情况是没有变量的,这个类就只有一个空参的构造器了,而空参构造器可以省略不写,同样也不会有实例变量的get/set方法,toString暂时也不需要。
所以一上来就只有几个对象,这几个对象里面也没有具体参数,小括号其实也可以省略。
所以最终看到的就是这样:
public enum Status { //员工的状态可以声明为枚举类
BUSY,FREE,VOCATION,DIMISSION;
}
直接实例化了四个对象而不是写了四个字符串值,使用的时候可以直接拿对象的变量名去使用,比定义四个字符串的写法简洁。
代码
【Status.java】
package yuyi06.apply;
/**
* ClassName: Status
* Package: yuyi06.apply
* Description: 定义员工的状态
* 就职状态:Busy(忙碌)、Free(空闲)、Vocation(休假)、Dimission(离职)
* @Author 雨翼轻尘
* @Create 2023/12/4 0004 15:51
*/
public enum Status { //员工的状态可以声明为枚举类
BUSY,FREE,VOCATION,DIMISSION;
}
【Employee.java】
package yuyi06.apply;
/**
* ClassName: Employee
* Package: yuyi06.apply
* Description:
*
* @Author 雨翼轻尘
* @Create 2023/12/4 0004 15:49
*/
public class Employee {
private String name;
private int age;
private Status status; //枚举类Status就可以看作是一个类,它作为引用数据类型的变量,作为当前类的成员变量是没有问题的
public Employee() {
}
public Employee(String name, int age, Status status) {
this.name = name;
this.age = age;
this.status = status;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' + //name本身是String类型,String中重写了toString,所以可以打印字符串的值
", age=" + age + //age是基本数据类型,直接打印它的值
", status=" + status + //status会调用它的toString,因为Status是enum类型,里面也有toString,直接打印名字
'}';
}
}
【EmployeeTest.java】
package yuyi06.apply;
/**
* ClassName: EmployeeTest
* Package: yuyi06.apply
* Description:
*
* @Author 雨翼轻尘
* @Create 2023/12/4 0004 16:05
*/
public class EmployeeTest {
public static void main(String[] args) {
Employee e1=new Employee("Jully",21,Status.BUSY); //枚举类直接用即可
System.out.println(e1); //打印的时候不是e1的地址
}
}
输出结果
题目描述
案例:使用枚举类实现单例模式
☕分析
“枚举类”若是只有一个对象,那就可以写成“单例模式”。
这里写两种方法,jdk5.0之前的和jdk5.0的写法。
【单例模式–饿汉式】
//饿汉式
class Bank1{
//1.私有化构造器
private Bank1(){
}
//2.创建当前类的实例
private static Bank1 instance=new Bank1();
//3.提供get方法
public static Bank1 getInstance(){
return instance;
}
}
现在改一改,刚才说枚举类的时候,不是通过方法去调的,直接拿类去调用。
所以就不用再提供get方法了。
创建实例的时候,直接将private改为public
,还要将创建的对象加一个final
。
public static final Bank1 instance=new Bank1();
对于变量instance,体现为两个角度,一个角度是获取它的值new Bank1()
,一个角度就是设置它的值。
“单例模式的饿汉式”将变量私有化(private)了,所以需要提供get方法来获取它的值。
现在将它加上public
了,所以出了类Bank1之后,可以来调用这个变量了。
而调用的时候有可能被赋予不合适的值,比如null:Bank1.instance=null;
这就相当于没有实例了,这不合适,所以变量需要用final
来修饰一下。
【jdk5.0之前】
//jdk5.0之前的使用枚举类定义单例模式
class Bank1{
//1.私有化构造器
private Bank1(){
}
//2.创建当前类的实例
public static final Bank1 instance=new Bank1();
}
【jdk5.0】
//jdk5.0
enum Bank2{
CPB; //没有具体实例变量,构造器也省略了,直接写即可
}
再比如:
enum GirlFriend{
XIAOMEI(20);
//实例变量
private final int age;
private GirlFriend(int age){
this.age=age;
}
}
jdk5.0之前自己造的时候那些修饰就省略了,如下:
代码
package yuyi06.exer1;
/**
* ClassName: BankTest1
* Package: yuyi06.exer1
* Description:
*
* @Author 雨翼轻尘
* @Create 2023/12/4 0004 17:54
*/
public class BankTest1 {
public static void main(String[] args) {
System.out.println(GirlFriend.XIAOMEI); //调用XIAOMEI的toString方法,默认打印它的名字
}
}
//jdk5.0之前的使用枚举类定义单例模式
class Bank1{
//1.私有化构造器
private Bank1(){
}
//2.创建当前类的实例
public static final Bank1 instance=new Bank1();
}
//jdk5.0使用enum关键字定义枚举类的方式去定义单例模式
enum Bank2{
CPB; //没有具体实例变量,构造器也省略了,直接写即可
}
enum GirlFriend{
XIAOMEI(20);
//自己造(jdk5.0)
//public static final GirlFriend XIAOLI=new GirlFriend(21);
//实例变量
private final int age;
private GirlFriend(int age){
this.age=age;
}
}
输出结果
题目描述
案例:颜色枚举类Color(使用enum声明)
1、声明颜色枚举类:7个常量对象:RED, ORANGE, YELLOW, GREEN, CYAN, BLUE,PURPLE;
2、在测试类中,使用枚举类,获取绿色对象,并打印对象。
代码
【Color.java】
package yuyi06.exer2;
/**
* ClassName: Color
* Package: yuyi06.exer2
* Description:
* 1、声明颜色枚举类:7个常量对象:RED, ORANGE, YELLOW, GREEN, CYAN, BLUE,PURPLE;
* @Author 雨翼轻尘
* @Create 2023/12/5 0005 10:02
*/
public enum Color {
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE,PURPLE;
}
【ColorTest.java】
package yuyi06.exer2;
/**
* ClassName: ColorTest
* Package: yuyi06.exer2
* Description:
* 2、在测试类中,使用枚举类,获取绿色对象,并打印对象。
* @Author 雨翼轻尘
* @Create 2023/12/5 0005 10:04
*/
public class ColorTest {
public static void main(String[] args) {
System.out.println(Color.GREEN);
}
}
输出结果
题目描述
案例拓展:颜色枚举类(使用enum
声明)
(1)声明颜色枚举类Color:
(2)在测试类中,使用枚举类,获取绿色对象,并打印对象。
提示:
7个常量对象名如下:
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE,PURPLE
代码
package yuyi06.exer3;
/**
* ClassName: ColorTest
* Package: yuyi06.exer3
* Description:
*
* @Author 雨翼轻尘
* @Create 2023/12/5 0005 10:09
*/
public class ColorTest {
public static void main(String[] args) {
System.out.println(Color.GREEN);
System.out.println(Color.CYAN);
}
}
enum Color{
//创建对象
RED(255,0,0,"红色"),
ORANGE(255,128,0,"橙色"),
YELLOW(255,255,0,"黄色"),
GREEN(0,255,0,"绿色"),
CYAN(0,255,255,"青色"),
BLUE(0,0,255,"蓝色"),
PURPLE(128,0,255,"紫色");
//属性
private final int red;
private final int green;
private final int blue;
public final String description; //颜色的描述
Color(int red, int green, int blue, String description) { //构造器加上private或者不加都可以,其实就是私有的,这是enum关键字在起作用(若试图将它写成public就会报错)
this.red = red;
this.green = green;
this.blue = blue;
this.description = description;
}
public int getRed() {
return red;
}
public int getGreen() {
return green;
}
public int getBlue() {
return blue;
}
public String getDescription() {
return description;
}
//重写toString方法
@Override
public String toString() {
//return super.toString()+"("+red+","+green+","+blue+")->"+description; //第一种写法 super.toString()
return name()+"("+red+","+green+","+blue+")->"+description; //第二种写法 name()
}
}
输出结果
注意
构造器加上private
或者不加都可以,其实就是私有的,这是enum关键字在起作用(若试图将它写成public就会报错)
Color(int red, int green, int blue, String description) { //构造器加上private或者不加都可以,其实就是私有的,这是enum关键字在起作用(若试图将它写成public就会报错)
this.red = red;
this.green = green;
this.blue = blue;
this.description = description;
}
若此时枚举类里面没有对象,这里会自动加上一个分号,意思是当前没有对象,如下:
若将这个分号去掉,就会报错: