Java枚举(Enum)
枚举
定义:
-
Java枚举是一种特殊的类,用来表示一组固定的常量。
-
被enum关键字修饰的类型就是枚举类型
(如果枚举不添加任何方法,枚举值默认为从0开始的有序数据。
比如定义一个枚举类表示季节,那里面有春、夏、秋和冬四个变量。
一个枚举类表示星期,那里面有星期一、星期二、星期三、星期四、星期五、星期六和星期日七个变量
枚举类表示月份就同理有十二个月、十二个变量。
-
格式:
- Java 枚举类使用 enum 关键字来定义,
enum
关键字的作用就像是class
和interface
。 - 各个常量使用逗号 , 来分割。注意最后一个枚举对象要使用“;”结尾,说明枚举值结束使用。
- Java 枚举类使用 enum 关键字来定义,
-
1 枚举的本质:其实就是终止类,并继承Enum抽象类。
2 枚举中的变量,其实就是一个当前类型的静态常量。
-
枚举类型本质上是java.lang.Enum类的子类,(java.lang.Enum是一个抽象类)但Java中不支持多继承,因此枚举类型不能再继承其他类。
//测试类
public enum Season { //上文说的季节类//每个成员变量都默认被 public final static修饰SPRING, SUMMER, AUTUMN, WINTER;
}
//测试类
public class SeasonTest {public static void main(String[] args) {for (Season seasonEnum : Season.values()) {System.out.println(seasonEnum+",ordinal:"+seasonEnum.ordinal()+",name:"+seasonEnum.name());}}
}
- 每个被枚举的成员其实就是定义的枚举类型的一个实例,它们都被默认为final。无法改变常数名称所设定的值,它们也是public和static的成员,这与接口中的常量限制相同。可以通过类名称直接使用它们。
枚举中的方法
-
values() :返回enum实例的数组,而且该数组中的元素严格保持在enum中的声明时的顺序。
-
name():返回实例名。
-
ordinal():返回实例声明时的次序,从0开始
-
getDeclaringClass():返回实例所属的enum类型。
-
equals():判断是否为同一个对象
也可以使用"=="来比较enum实例
-
valueOf():返回指定字符串值的枚举常量。
特性
- 除了不能继承,可以将enum看作一个普通类。
- Java不允许使用
=
为枚举常量赋值。 - enum通过方法来显式赋值
- enum可以添加普通方法、静态方法、抽象方法、构造方法。
- 枚举可以实现接口
- 枚举不可以继承
枚举类中定义抽象方法
既然编译器最终将每个枚举值声明为枚举类的实例,那我们能在枚举类中声明抽象方法让枚举值去实现么?
在枚举类Season中声明了一个抽象方法sayHello()。然后在创建枚举值时,就必须实现该抽象方法
public enum SeasonEnum {//枚举类的实例对象必须在最前面先定义,而且必须每个实例对象都必须维护上chinese成员变量SPRING("春天",1201){@Overridevoid sayHello() {System.out.println("hello spring");}},SUMMER("夏天",1202){@Overridevoid sayHello() {System.out.println("hello summer");}},AUTUMN("秋天",1203){@Overridevoid sayHello() {System.out.println("hello autumn");}},WINTER("冬天",1204){@Overridevoid sayHello() {System.out.println("hello winter");}};private String name;private Integer code;//枚举类型的构造函数默认为private,因为枚举类型的初始化要在当前枚举类中完成。SeasonEnum (String name,Integer code){this.name=name;this.code=code;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}abstract void sayHello();
}
测试类:
public class SeasonTest {public static void main(String[] args) {//直接初始化SeasonEnum season1 = SeasonEnum.SPRING;//调用SeasonEnum枚举类的sayHello方法season1.sayHello();}
}
控制台输出:
hello spring
-
枚举允许继承类吗?
枚举类使用enum定义后在编译后默认继承了java.lang.Enum类,而不是普通的继承Object类。enum声明类继承了Serializable和Comparable两个接口。且采用enum声明后,该类会被编译器加上final声明(同String),故该类是无法继承的。
所有枚举类都默认是Enum类的子类,无需我们使用extends来继承。
- 枚举允许实现接口吗?
枚举允许实现接口。因为枚举本身就是一个类,类是可以实现多个接口的。
public interface EnumInterface {public abstract void print(); } public enum SizeEnum implements EnumInterface{BIG,MIDDLE,SMALL;@Overridepublic void print() {System.out.println("继承接口-重写方法一次");} }
- 枚举可以用等号比较吗?
肯定,因为在Enum类里面,已经重写了equals方法,而方法里面比较就是直接使用==,来比较2个对象的。所以,你在外边直接使用==也是可以的。
- 可以继承枚举吗?
当然不能呀,枚举类默认继承了java.lang.Enum类,一个类怎么能继承两个类呢?
- 枚举可以实现单例模式吗?
枚举本身就是一种对单例设计模式友好的形式,它是实现单例模式的一种很好的方式。
public class InstanceDemo {/*** 构造方法私有化*/private InstanceDemo(){}/*** 返回实例* @return*/public static InstanceDemo getInstance() {return Singleton.INSTANCE.getInstance();}/*** 使用枚举方法实现单利模式*/private enum Singleton {INSTANCE;private InstanceDemo instance;/*** JVM保证这个方法绝对只调用一次*/Singleton() {instance = new InstanceDemo();}public InstanceDemo getInstance() {return instance;}}//测试一下public static void main(String[] args) {InstanceDemo one = InstanceDemo.getInstance();InstanceDemo two = InstanceDemo.getInstance();System.out.println(one);System.out.println(two);System.out.println(one == two);} }
创建的对象相同
csdn.test.recursion.demo.InstanceDemo@74a14482 csdn.test.recursion.demo.InstanceDemo@74a14482 true
- 当使用compareTo()比较枚举时,比较的是什么?
int compareTo(E e):比较两个枚举常量谁大谁小,其实比较的就是枚举常量在枚举类中声明的顺序;返回值可以仔细看看源码;
一起看看,底层代码吧
public final int compareTo(E o) {Enum<?> other = (Enum<?>)o;Enum<E> self = this;if (self.getClass() != other.getClass() && // optimizationself.getDeclaringClass() != other.getDeclaringClass())throw new ClassCastException();return self.ordinal - other.ordinal;}
举个例子你就能理解了
public class TestSeasonEnum {public static void main(String[] args) {Season season = Season.SPRING;Season season1 = Season.SUMMER;Season season2 = Season.AUTUMN;Season season3 = Season.WINTER;System.out.println(season.compareTo(season1));System.out.println(season.compareTo(season2));System.out.println(season.compareTo(season3));} }
输出结课,详情参考源码一看便知道
-1
-2
-3- 当使用equals()比较枚举的时候,比较的是什么?
枚举类型的equals()方法比较的是枚举类对象的内存地址,作用与等号等价。