枚举类介绍
如果一个类的实例是有限且确定的
,那么可以使用枚举类
。比如:季节类,只有春夏秋冬四个实例
。
枚举类使用enum进行创建,其实例必须从”第一行“开始显示写出。
enum Season{
SPRING,SUMMER,FALL,WINTER;//默认public static final,这都是Season类的对象。
}
特点
1、枚举类的对象默认都是public static final
2、枚举类的构造器都是private,所以无法在外部创建其实例,这也决定了枚举类实例的个数的确定性(写了几个就是几个)。
3、enum类不可被继承。
4、enum类默认extends java.lang.Enum,所以无法再继承其他类
问题
enum类默认被final修饰的情况下,是无法有子类的
《疯狂Java讲义》中
@Getter
enum Season{
// SPRING,SUMMER,FALL,WINTER;//默认public static final,这都是Season类的对象。
SPRING{
public void show(){
System.out.println("I'm Spring");
}
},SUMMER,FALL,WINTER;
private String name;
//构造器默认且只能是private
Season(){
System.out.println("Season run...");//运行四次
}
public void setName(){
//Java5开始,switch方法支持枚举类对象。
switch(this){
case SPRING:
name="春";
break;
case SUMMER:
name="夏";
break;
case FALL:
name="秋";
break;
case WINTER:
name="冬";
break;
}
}
public void setName1(String name){
this.name=name;
}
public void show(){
System.out.println("I'm show");
}
}
问题:SPRING
是Season匿名子类的对象
,但是前面已经说明Season类是final的?
1、当在enum类
中创建匿名子类对象
的时候,在运行时,会将Season编译为一个.class文件
,没有final修饰
:
同时对于匿名子类
,会生成一个.class文件:
2、当enum类中没有匿名子类对象
时,对应的class就是final的
:
3、如果enum类中含有抽象方法
,那么这个类就是抽象的
:给出的对象必须实现抽象方法
:
即便如此,还是无法继承该类
结论
1、enum类实际上是不存在final或者abstract的
,就是不能被继承
。如果像《疯狂Java讲义》中说的,非抽象枚举类默认是final的,那么应该可以显示用final修饰,但是不行:
所以说,enum本身不存在final、abstract的说法
。就是不能被继承
。运行时生成的class
才有final、abstract的说法
。
2、运行时,会生成对应的.class文件
(可以理解为一个新的class类型的类)。
如果enum类中 没有抽象方法 ,也 没有匿名子类对象 ,那么这个类是被 final修饰 的。
如果enum类中 有抽象方法 ,那么 这个类是抽象的 ,对象 必须实现 该抽象方法。
如果enum类中 没有抽象方法 ,但是 有匿名子类对象 ,那么 这个类不被final修饰,也不是抽象的
实战
注入整个包
在使用 enum 类
中的静态方法
或者 enum 枚举
时,可以直接把 enum 整个包 import
@Getter
@AllArgsConstructor
public enum HumanTypeEnum {
MAN(0, "男"),
FEMALE(1, "女")
private int type;
private String remark;
public static String getValue(String type) {
....
}
public static final List<xxxx> ALL_TYPE = new ArrayList<>();
static {
//功能授权
ALL_TYPE.addAll(Arrays.asList(MAN, FEMALE));
}
}
使用 enum
import static com.xxxx.common.HumanTypeEnum.*;
@Slf4j
@Service("userService")
public class UserServiceImpl implements UserService {
ALL_TYPE.forEach(info -> xxxx)
}
带有构造方法的枚举 带有抽象方法的枚举
enum 关键字定义的枚举类都默认继承了Enum 类(抽象类)
、该类位于 java.lang下、该类具有两个 final 常量:
name :枚举常量,如上例中的 SUN MON 等
ordinal :类似数组索引,即位置(position)的意思,默认值从0开始
下为Enum类的部分源码:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
// The name of this enum constant, as declared in the enum declaration.
private final String name;
public final String name() {
return name;
}
public String toString() {
return name;
}
/**
* The ordinal of this enumeration constant (its position in the enum declaration,
* where the initial constant is assigned an ordinal of zero).
*/
private final int ordinal;
public final int ordinal() {
return ordinal;
}
// Sole constructor. Programmers cannot invoke this constructor.
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
}
实现带有构造方法的枚举(项目中常使用的方式)
public enum Sex {
MALE(1, "男"),
FEMALE(2, "女");
public final Integer type;
public final String value;
private Sex(Integer type, String value){
this.type = type;
this.value = value;
}
}
public class SexEnumTest {
public static void main(String[] args) {
Sex man = Sex.MALE;
System.out.println(man); // MALE 调用默认的toString()
System.out.println(man.name()); // MALE
System.out.println(man.ordinal()); // 0
System.out.println(man.type); // 1
System.out.println(man.value); // 男
}
}
抽象方法
带有抽象方法的枚举
、在上例的基础上添加一个抽象方法
public enum Sex {
MALE(1, "男"){
@Override
public void haircut() {
System.out.println("剃个光头吧~");
}
},
FEMALE(2, "女"){
@Override
public void haircut() {
System.out.println("还是留长发吧~");
}
};
public final Integer type;
public final String value;
private Sex(Integer type, String value){
this.type = type;
this.value = value;
}
public abstract void haircut();
}
public class SexEnumTest {
public static void main(String[] args) {
Sex man = Sex.MALE;
System.out.println(man); // MALE 调用默认的toString()
System.out.println(man.name()); // MALE
System.out.println(man.ordinal()); // 0
System.out.println(man.type); // 1
System.out.println(man.value); // 男
man.haircut(); // 剃个光头吧~
Sex.FEMALE.haircut(); // 还是留长发吧~
}
}