Java 中为什么枚举类只能有私有构造函数?

2023-03-05  本文已影响0人  flyjar

1、先说一下枚举类型的前世今生,为什么会有枚举呢?

单例设计模式:在一些系统中,有的类被规定只能提供一个实例化对象,这时就可以使用单例设计模式。这时就可以将构造方法私有化进行封装使得在类的外部无法实例化新的对象,而在类的内部进行实例化对象的创建,并且提供共有的getInstance方法返回固定的实例化对象。类的这种设计模式就称为单例设计模式。单例设计模式分为饿汉式和懒汉式。

public class SingleObject {
    private final String name = "阿里云";
    private static final SingleObject SINGLE = new SingleObject();//只产生一份实例化对象
    private SingleObject() {}   //构造方法私有化,再类的外部无法new新对象
 
    /**
     * 获取本地实例化对象,使用static修饰不收实例化对象的限制
     * @return  SINGLE内部实例化对象
     */
    public static SingleObject getInstance() {
        return SINGLE;  //返回单一对象SINGLE
    }
    @Override
    public String toString() {
        return name;
    }
}
public class SingleObjectTestDrive {
    public static void main(String[] args) {
        SingleObject singleObject = SingleObject.getInstance();
        System.out.println(singleObject);
    }
}
private static final SingleObject INSTANCE;
......
public SingleObject getInstance() {
    if(INSTANCE == null) {
        INSTANCE = new SingleObject;
    }
    return INSTANCE;
}

多例设计模式:类似于单例设计模式在一个系统中,有的类可能需要固定个数的特定的实例化对象,如四季,只有春夏秋冬,这个时候就应当限制对象的实例化,而不是由用户随意的实例化对象。这是就可以使用多例设计模式在类的内部提供好实例化对象后进行类的封装,然后提供给用户固定的实例化对象。

多例设置模式的实例:

public class Season {
    private String season;
    private String desc;
    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("春天","寒冷");
    private Season(String season,String desc) {//构造方法私有化,在类的外部无法进行对象的实例化
        this.season = season;
        this.desc = desc;
    }
    @Override
    public String toString() {
        return "Season{" +
                "season='" + season + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

2、枚举
为了解决单例设计模式和多利设计模式的缺陷问题,自JDK1.5之后,Java提供了通过enum关键字定义的枚举结构,对多例设计模式进行简化。
使用enum关键字定义枚举类时的注意事项:

使用枚举实现多例设计模式中的类体:

public enum Season {
   //枚举对象必须定义在枚举类的行首
   SPRING("春天","温暖"),//这里相当于将public static final Season season = new Season("春天","温暖")进行了简写
   SUMMER("夏天","炎热"),
   AUTUMN("秋天","凉爽"),
   WINTER("冬天","寒冷");
   private String season;    //描述季节的属性
   private String desc;       //描述季节的特征的属性
   //提供对应枚举类定义的构造方法
   private Season(String season,String desc) {
       this.season = season;
       this.desc = desc;
   }
   @Override   //覆写父类中的toString方法
   public String toString() {
       return "Season{" +
               "season='" + season + '\'' +
               ", desc='" + desc + '\'' +
               '}';
   }
}
class TestsMain() {
   public static void main(String[] args) {
       Season spr = Season.SPRING;
       System.out.println(spr);//输出:Season{season='春天', desc='温暖'}
       System.out.println(Arrays.toStirng(Season.values()));//values方法返回所有的枚举对象,于一个Season[]数组中
   }
}

对于通过enum关键字定义的枚举类默认继承自Enum类可以通过反编译进行证明:

对上述的Seaon枚举类进行反编译:

26a949c0e3c14e37a7c44a8521817ece.png

Enum类
使用enum关键字定义的枚举类,是默认被final关键字修饰并且继承自Enum父类的,观察Enum父类,可以知道通过在enum关键字定义的枚举类中的枚举对象的名称存在于Enum父类的name属性中的:

cd6ab52eb31b4a48b2a57aed87ae50ea.png

Enum父类中提供了很多操作枚举对象的方法:

@Override   //覆写父类中的toString方法,用于输出当前枚举对象的信息
    public String toString() {
        return "Season{" +
                "season='" + season + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }

返回当前的枚举对象名称。该方法在父类中通过final关键字修饰,子类中不能进行覆写。

//创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
Season spring = Season.SPRING;
System.out.println(spring.name());//调用当前枚举对象的name方法,输出SPRING
//创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
for (Season temp : Season.values()) {    //for each遍历Season类型的枚举对象
   System.out.println(temp.ordinal());   //输出每一个枚举对象的编号
}
//输出:0 1 2 3
//创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
System.out.println(Arrays.toString(Season.values()));
//输出:[Season{season='春天', desc='温暖'}, Season{season='夏天', desc='炎热'}, Season{season='秋天', desc='凉爽'}, Season{season='冬天', desc='寒冷'}]
//创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
System.out.println(Season.valueOf("SUMMER").ordinal());
//输出:1
//创建了一个枚举类Season,四个枚举对象SPRING,SUMMER,AUTUMN,WINTER
System.out.println(Season.AUTUMN.compareTo(Season.SPRING));
//输出:2

总结

上一篇 下一篇

猜你喜欢

热点阅读