`

3. 用私有构造器或枚举类型强化singleton属性

阅读更多

Effective Java 中提出实现单例的3中方法,详细内容如下:

1.将公有静态成员变量做成final域

package com.jason.effectivejava.rule3.one;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Elvis {

	public static final Elvis INSTANCE = new Elvis();

	private Elvis() {
               //it is very import for this type
		if(INSTANCE != null){
			throw new IllegalArgumentException("No exist the second instance");
		}
	}

	public void leaveTheBuilding() {

		System.out.println("Whoa baby, I'm outta here!");

	}

	public static void main(String[] args) {

		Elvis singleton = Elvis.INSTANCE;
		singleton.leaveTheBuilding();
		Constructor[] arrayConstructor = singleton.getClass().getDeclaredConstructors();
		arrayConstructor[0].setAccessible(true);
		
		try {
			arrayConstructor[0].newInstance();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 注意:为了防止特殊用户通过AccessibleObject.setAccessible方法,利用反射机制访问私有构造函数,创建新的实例,应在私有构造函数中添加判断,阻止创建新的实例。

测试结果如下:

Whoa baby, I'm outta here!
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
	at com.jason.effectivejava.rule3.Elvis.main(Elvis.java:30)
Caused by: java.lang.IllegalArgumentException: No exist the second instance
	at com.jason.effectivejava.rule3.Elvis.<init>(Elvis.java:12)
	... 5 more

2.将公有成员变量做成静态工厂方法

package com.jason.effectivejava.rule3.two;

public class Elvis {

	private static final Elvis INSTANCE = new Elvis();

	private Elvis() {
	}

	public static Elvis getInstance() {
		return INSTANCE;
	}

	public void leaveTheBuilding() {

		System.out.println("Whoa baby, I'm outta here!");
	}

	// 必须提供该方法,以便重新指定反序列化得到的对象.
	private Object readResolve(){

		return INSTANCE;
	}

	public static void main(String[] args) {

		Elvis elvis = Elvis.getInstance();
		elvis.leaveTheBuilding();
	}
}

3.单元素枚举类型

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
*
*枚举实现单例
*<p>目前最好的方式,避免了反射的攻击和序列化的问题
*
*反射调用枚举私有构造函数测试结果:
* Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.book.chap2.singleton.Singleton3.main(Singleton3.java:34)
*
*/

public enum Elvis {

	INSTANCE;

	public void leaveTheBuilding() {

		System.out.println("Whoa baby, I'm outta here!");
	}

	public static void main(String[] args) {

		Elvis elvis = Elvis.INSTANCE;
		elvis.leaveTheBuilding();
		
		//测试,是否可以反射生成枚举,利用反射调用私有构造器
		Constructor[] arrayConstructor=Elvis.INSTANCE.getClass().getDeclaredConstructors();

		arrayConstructor[0].setAccessible(true);
		try {
			arrayConstructor[0].newInstance();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

 试结果:

Whoa baby, I'm outta here!
java.lang.IllegalArgumentException: Cannot reflectively create enum objects
	at java.lang.reflect.Constructor.newInstance(Constructor.java:511)
	at com.jason.effectivejava.rule3.two.Elvis.main(Elvis.java:36)

 总结:

在三种方法中,单元素枚举类型的单例,代码简洁,无偿提供序列化机制,同时可防止多次实例化,在实际中应该是最佳选择。

分享到:
评论

相关推荐

    spring.net中文手册在线版

    设置索引器属性 4.3.3.5.内联对象定义 4.3.3.6.idref节点 4.3.3.7.引用协作对象 4.3.3.8.value和ref节点的简短格式 4.3.3.9.复合属性名 4.3.4.方法注入 4.3.4.1.查询方法注入 4.3.4.2.替换任意方法 4.3.5.引用其他...

    单例模式Singleton(java源码)

    Singleton拥有一个私有构造函数,确保用户无法通过new直接实例化它。除此之外,该模式中包含一个静态私有成员变量instance与静态公有方法Instance()。Instance()方法负责检验并实例化自己,然后存储在静态成员变量中...

    Spring-Reference_zh_CN(Spring中文参考手册)

    3.3.3. bean属性及构造器参数详解 3.3.3.1. 直接量(基本类型、Strings类型等。) 3.3.3.2. 引用其它的bean(协作者) 3.3.3.3. 内部bean 3.3.3.4. 集合 3.3.3.5. Nulls 3.3.3.6. XML-based configuration metadata ...

    Spring中文帮助文档

    7.10.3. 原型目标源 7.10.4. ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. ...

    Spring API

    7.10.3. 原型目标源 7.10.4. ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. ...

    spring chm文档

    3.3.3. bean属性及构造器参数详解 3.3.4. 使用depends-on 3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.7. 依赖检查 3.3.8. 方法注入 3.4. bean的作用域 3.4.1. Singleton作用域 3.4.2. ...

    Spring 2.0 开发参考手册

    3.3.3. bean属性及构造器参数详解 3.3.4. 使用depends-on 3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.7. 依赖检查 3.3.8. 方法注入 3.4. bean的作用域 3.4.1. Singleton作用域 3.4.2. ...

    单例极致 singleton C++

    3、有构造函数,构造函数有没有参数版本(DEFINE_SINGLETON_CONSTRUCT_WITH_DEFAULT); 4、有构造函数,构造函数都有参数(DEFINE_SINGLETON_CONSTRUCT); 通过宏定义巧妙实现,使用也很方便!

    singleton_code.zip

    文件名 : Singleton1.java 文件名 : Singleton2.java 文件名 : Singleton3.java 文件名 : Singleton4.java 文件名 : Singleton5.java 文件名 : Singleton6.java 文件名 : TestSingleton1.java 文件名 : ...

    运行xml文件的类AnimatePacker.h、AnimatePacker.cpp、Singleton.h

    运行xml文件的类AnimatePacker.h、AnimatePacker.cpp、Singleton.h

    Singleton两种代码实现

    单例模式,Singleton两种代码实现。一般实现方法,泛型实现方法(推荐)

    设计模式精解-GoF 23 种设计模式解析附 C++实现源码.rar

    1.2 AbstactFactory模式 ..........................................................................................................11 1.3 Singleton模式 .....................................................

    Singleton.cs

    单例帮助类,只要继承此类就可以实现单例.

    Singleton pattern单例模式应用

    Singleton pattern单例模式应用

    javaee视频.zip

    3,输人输出3rar 4线程创建rar 5.TCP.rar 6UDP.rar 7HTMl介绍+Tomcat安装ra 8.Servleti置版流程raI 9ava开发环蟯ra 10简单程序和程图.ran 11变星和基础数据类型.ra 12运算符和表达式ra 13.流程控制rar 14数组.rar 15...

    C++完美实现Singleton模式

    C++完美实现Singleton模式

    Java 面试宝典

    19、构造器 Constructor 是否可被 override? ................................................................ 15 20、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继 承具体类...

    Java 单例模式Singleton

    简单的单例模式举例Singleton 分为恶汉式 懒汉式

    Singleton.h

    Qt单例模板类。不用再每次去写单例了,按照文件描述操作步骤,就是快速实现单例。我之前同事写的,嘿嘿,我就拿过来mark~ 调不了积分,有需要请留言~

Global site tag (gtag.js) - Google Analytics