【深入Java枚举类:不仅仅是常量的容器】
前言:
Java 枚举类(
enum
)是一种特殊的数据类型,用来定义一组预定义的常量。枚举类不仅可以包含常量,还能定义方法、字段和构造器,使其功能更加强大和灵活。
引入
【1】数学:枚举法:
1<x<4
2<y<5
求x+y=6
枚举法:一枚一枚的列举出来。前提:有限,确定
【2】在java中,类的对象是有限个,确定的。这个类我们可以定义为枚举类。
举例:
星期:一二三四五六日
性别:男女
季节:春夏秋冬
【3】自定义枚举类:
(JDK1.5之前自定义枚举类)
/*** @Auther: themyth* 定义枚举类:季节*/
public class Season {//属性: 属性的值不能变private final String seasonName ;//季节名字private final String seasonDesc ;//季节描述//利用构造器对属性进行赋值操作://构造器私有化,外界不能调用这个构造器,只能Season内部自己调用private Season(String seasonName,String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//提供枚举类的有限的 确定的对象: 对象的值不能变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("冬天","冰天雪地");//额外因素:public String getSeasonName() {return seasonName;}public String getSeasonDesc() {return seasonDesc;}//toString():@Overridepublic String toString() {return "Season{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}
}
测试类:
/*** @Auther: themyth*/
public class TestSeason {//这是一个main方法,是程序的入口:public static void main(String[] args) {Season summer = Season.SUMMER;System.out.println(summer/*.toString()*/);System.out.println(summer.getSeasonName());}
}
结果:
(JDK1.5以后使用enum关键字创建枚举类):
变为下面的枚举类:
/*** @Auther: themyth* 定义枚举类:季节*/
public enum Season {//提供枚举类的有限的 确定的对象: 对象的值不能变--->enum枚举要求对象(常量)必须放在最开始的位置//多个对象之间用,进行连接,最后一个对象后面用;结束SPRING("春天","春暖花开"),SUMMER("夏天","烈日炎炎"),AUTUMN("秋天","硕果累累"),WINTER("冬天","冰天雪地");//属性: 属性的值不能变private final String seasonName ;//季节名字private final String seasonDesc ;//季节描述//利用构造器对属性进行赋值操作://构造器私有化,外界不能调用这个构造器,只能Season内部自己调用private Season(String seasonName, String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//额外因素:public String getSeasonName() {return seasonName;}public String getSeasonDesc() {return seasonDesc;}//toString():@Overridepublic String toString() {return "Season{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}
}
使用枚举类:
注意:先将Season枚举类里面的toString()方法注释掉
/*** @Auther: themyth*/
public class TestSeason {//这是一个main方法,是程序的入口:public static void main(String[] args) {Season winter = Season.WINTER;System.out.println(winter);//enum关键字对应的枚举类的上层父类是:java.lang.Enum//但是我们自定义的枚举类的上层父类:ObjectSystem.out.println(Season.class.getSuperclass().getName());}
}
在源码中经常看到别人定义的枚举类形态:
public enum Season {//相当于Season下面有四个对象(常量),并且它们前面的修饰符都是public static final,后面相当于在调用空构造器,只是这儿可以省略SPRING,SUMMER(),//括号可以省略。AUTUMN(),WINTER;
}
为什么这么简单:因为这个枚举类底层没有属性,属性,构造器,toString,get方法都删掉不写了,然后按理来说应该写为:SPRING() 现在连()可以省略 就变成 SPRING
看到的形态就剩:常量名(对象名)
案例:
Thread中的枚举类:State
public enum State {/*** Thread state for a thread which has not yet started.*/NEW,/*** Thread state for a runnable thread. A thread in the runnable* state is executing in the Java virtual machine but it may* be waiting for other resources from the operating system* such as processor.*/RUNNABLE,/*** Thread state for a thread blocked waiting for a monitor lock.* A thread in the blocked state is waiting for a monitor lock* to enter a synchronized block/method or* reenter a synchronized block/method after calling* {@link Object#wait() Object.wait}.*/BLOCKED,/*** Thread state for a waiting thread.* A thread is in the waiting state due to calling one of the* following methods:* <ul>* <li>{@link Object#wait() Object.wait} with no timeout</li>* <li>{@link #join() Thread.join} with no timeout</li>* <li>{@link LockSupport#park() LockSupport.park}</li>* </ul>** <p>A thread in the waiting state is waiting for another thread to* perform a particular action.** For example, a thread that has called <tt>Object.wait()</tt>* on an object is waiting for another thread to call* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on* that object. A thread that has called <tt>Thread.join()</tt>* is waiting for a specified thread to terminate.*/WAITING,/*** Thread state for a waiting thread with a specified waiting time.* A thread is in the timed waiting state due to calling one of* the following methods with a specified positive waiting time:* <ul>* <li>{@link #sleep Thread.sleep}</li>* <li>{@link Object#wait(long) Object.wait} with timeout</li>* <li>{@link #join(long) Thread.join} with timeout</li>* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>* </ul>*/TIMED_WAITING,/*** Thread state for a terminated thread.* The thread has completed execution.*/TERMINATED;}
Enum类中的常用方法
/*** @Auther: themyth*/
public class TestSeason {//这是一个main方法,是程序的入口:public static void main(String[] args) {//用enum关键字创建的Season枚举类上面的父类是:java.lang.Enum,常用方法子类Season可以直接拿来使用//toString():--->获取对象的名字Season autumn = Season.AUTUMN;System.out.println(autumn/*.toString()*/);System.out.println("-----------------------");//values():--->返回枚举类对象的数组Season[] values = Season.values();for(Season s : values){System.out.println(s/*.toString()*/);}System.out.println("-----------------------");//valueOf(String name):通过对象名字获取这个枚举对象//注意:对象的名字必须传正确,否则抛出异常Season autumn1 = Season.valueOf("AUTUMN");System.out.println(autumn1);}
}
枚举类实现接口
定义一个接口:
/*** @Auther: themyth*/
public interface TestInterface {void show();
}
枚举类实现接口,并且重写show方法:
public enum Season implements TestInterface{SPRING,SUMMER,AUTUMN,WINTER;@Overridepublic void show() {System.out.println("这是Season...");}
}
测试类:
/*** @Auther: themyth*/
public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {Season autumn = Season.AUTUMN;autumn.show();Season summer = Season.SUMMER;summer.show();}
}
上面发现所有的枚举对象,调用这个show方法的时候走的都是同一个方法,结果都一样:
但是现在我想要:不同的对象 调用的show方法也不同:
public enum Season implements TestInterface{SPRING{@Overridepublic void show() {System.out.println("这是春天");}},SUMMER{@Overridepublic void show() {System.out.println("这是夏天");}},AUTUMN{@Overridepublic void show() {System.out.println("这是秋天");}},WINTER{@Overridepublic void show() {System.out.println("这是冬天");}};/* @Overridepublic void show() {System.out.println("这是Season...");}*/
}
测试类:
/*** @Auther: themyth*/
public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {Season autumn = Season.AUTUMN;autumn.show();Season summer = Season.SUMMER;summer.show();}
}
实际应用
/*** @Auther: themyth*/
public class Person {//属性:private int age;private String name;private Gender sex;//将枚举类作为一个属性public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Gender getSex() {return sex;}public void setSex(Gender sex) {this.sex = sex;}@Overridepublic String toString() {return "Person{" +"age=" + age +", name='" + name + '\'' +", sex='" + sex + '\'' +'}';}
}
/*** @Auther: themyth*/
public enum Gender {男,女;
}
/*** @Auther: themyth*/
public class Test {//这是一个main方法,是程序的入口:public static void main(String[] args) {Person p = new Person();p.setAge(19);p.setName("lili");p.setSex(Gender.男);//传入枚举类Gender的对象:--->在入口处对参数进行了限制System.out.println(p);}
}
还可以通过枚举结合switch处理:
/*** @Auther: themyth*/
public class Test02 {//这是一个main方法,是程序的入口:public static void main(String[] args) {Gender sex = Gender.男;//switch后面的()中可以传入枚举类型://switch后面的():byte,short,int,char,string,枚举switch (sex){case 女:System.out.println("是个女孩");break;case 男:System.out.println("是个男孩");break;}}
}