• 【面试题】Java单例设计模式-饿汉式枚举(enum)单例


    一、enum关键字

    enum关键字是在Java1.5也就是Java SE5之后引入的一个新特性:它通过关键字enum来定义一个枚举类,这个被定义的枚举类继承Enum类,这个枚举类算是一种特殊类,它同样能像其他普通类一样拥有构造器、方法,也能够实现接口,但是它不能再继承其他别的类,因为它的直接父类是Enum类,并且因为它默认的修饰符有final的存在,因此它无法直接派生出其他子类,除非将其使用abstract修饰。

    按照《Java编程思想》中的原话来说:关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件来使用。

    在枚举类出现之前Java是将常量放在接口或是放在普通类当中,然后使用public、static、final去修饰定义的常量,如下两个例子:

    public interface Constants2 {
        public static final int CONSTANT_1 = 1;
        public static final int CONSTANT_2 = 2;
        public static final int CONSTANT_3 = 3;
    }
    
    
    public class Constants {
        public static final int CONSTANT_1 = 1;
        public static final int CONSTANT_2 = 2;
        public static final int CONSTANT_3 = 3;
    }

    在枚举类型出现之后,就可以使用枚举类型来定义常量,这些枚举类型成员_1、_2、_3都默认被public、static、final修饰,语法如下:

    public enum Constants {
        CONSTANT_1,
        CONSTANT_2,
        CONSTANT_3
    }

    但是Java枚举类型输出其常量的时候不像C /C++的枚举那样是数字,输出的是其常量名,如果需要输出其类型成员声明时数字次序的话,需要调用ordinal()方法:

    public enum Singleton2 {
        SHERLOCK,
        WASTON;
    }
    
    class Main{
        public static void main(String[] args) {
            System.out.println(Singleton2.SHERLOCK);
            System.out.println(Singleton2.WASTON);
            System.out.println(Singleton2.SHERLOCK.ordinal());
            System.out.println(Singleton2.WASTON.ordinal());
        }
    }
    
    输出结果:
    SHERLOCK
    WASTON
    0
    1

    二、枚举单例的实现

    单例模式的特点有以下三个:

    • 1、单例类只能有一个实例。
    • 2、单例类必须自己创建自己的唯一实例。
    • 3、单例类必须给所有其他对象提供这一实例。

    我们可以发现枚举类型十分契合以上三个特点,并且我们通过创建枚举类型,可以发现它其中每一个类型成员其实都是Singleton2这个枚举类的一个实例。

    public enum Singleton2 {
        SHERLOCK
    }
    
    class Main{
        public static void main(String[] args) {
            Singleton2 sherlock = Singleton2.SHERLOCK;
            Singleton2 sherlock1 = Singleton2.SHERLOCK;
            System.out.println(sherlock == Singleton2.SHERLOCK);
            System.out.println(sherlock == sherlock1);
            System.out.println(Singleton2.SHERLOCK.getDeclaringClass());
        }
    }
    
    输出结果:
    true
    true
    class com.sherlock.singleton.Singleton2

    利用这个特性,我们就可以通过如下代码创建单例,同时又因为这个特性,决定了它只能属于饿汉式单例模式

    public enum Singleton2 {
        SHERLOCK;
        public void print() {
            System.out.println("I am Sherlock!");
        }
    }
    
    class Main{
        public static void main(String[] args) {
            Singleton2 sherlock = Singleton2.SHERLOCK;
            System.out.println(Singleton2.SHERLOCK.getDeclaringClass());
            sherlock.print();
        }
    }

    输出结果如下: 

    class com.sherlock.singleton.Singleton2
    I am Sherlock!

    三、枚举单例的优缺点

    优点:

    (1)能够避免多线程同步问题;

    (2)能够防止反序列化重新创建对象;

    (3)实现比起其它懒汉式、饿汉式单例来说十分简洁,阅读性好;

    缺点:

    (1)因为是饿汉式加载,所以会导致枚举实例会长期存在于内存当中;

  • 相关阅读:
    OI回忆录——一个过气OIer的制杖历程
    博客园美化手记——CSS javascript html
    ProjectEuler && Rosecode && Mathmash做题记录
    算法竞赛推荐
    2020智算之道复赛E 树数数
    牛客编程巅峰赛S1第9场
    c++小学期大作业攻略(五)基于QSS的样式美化
    c++小学期大作业攻略(四)任务系统+站内信
    c++小学期大作业攻略(三)用户系统
    c++小学期大作业攻略(零)建议+代码结构(持续更新)
  • 原文地址:https://www.cnblogs.com/SherLocked/p/12802139.html
Copyright © 2020-2023  润新知