高效Java03:使用私有构造器或枚举类型强化单例属性

来源:互联网 发布:矩阵怎么约分 编辑:程序博客网 时间:2024/05/21 14:48

单例(singleton)指仅仅只能被实例化一次的类,主要服务于一些需要保证对象只存在一个实例的场景。

实现方式一:暴露公有静态成员变量

public class Singleton {    public static final Singleton INSTANCE = new Singleton();    private Singleton() {    }}

INSTANCE为对外暴露的成员变量,构造方法设为私有。

实现方式二:暴露公有静态方法

public class Singleton {    private static final Singleton INSTANCE = new Singleton();    private Singleton() {    }    public static Singleton getInstance() {        return INSTANCE;    }}

实例成员INSTANCE与构造方法同时设为私有,通过静态成员方法getInstance()对外暴露访问。上面这种写法称作若饿汉模式,另外还有一种懒汉模式的写法,INSTANCE类加载时不初始化,在需要使用时才初始化。

public class Singleton {    private static Singleton INSTANCE = null;    private Singleton() {    }    public static Singleton getInstance() {        if (INSTANCE == null) {            INSTANCE = new Singleton();        }        return INSTANCE;    }}

懒汉模式存在线程安全问题,这里仅展示一下,不推荐使用。

实现方式三:包含单个元素的枚举类型

除了上面说到的两种方式,还有第三种实现单例的方法,即使用包含单个元素的枚举类型。

public enum Singleton {    INSTANCE;}

枚举为什么可以实现单例?

通过对上面代码编译后的Singleton.class反编译后得到下面的代码:

public final class Singleton extends Enum {    public static final Singleton INSTANCE;    private static final Singleton $VALUES[];    static {        INSTANCE = new Singleton("INSTANCE", 0);        $VALUES = (new Singleton[]{                INSTANCE        });    }    public static Singleton[] values() {        return (Singleton[]) $VALUES.clone();    }    public static Singleton valueOf(String name) {        return Enum.valueOf(Singleton.class, name);    }    private Singleton(String s, int i) {        super(s, i);    }}

通过反编译后的代码我们可以看到,枚举实际上与我们写的普通类并无太大区别,只不过编译器帮我们简化了这部分工作。我们前面实现单例是将类的实例控制为一个,而枚举是类中定义了N个元素,则将类的实例控制为N个,所以当我们在枚举类中只定义一个元素时即可实现单例的效果。

0 0