Effective Java之用私有构造器或者枚举类型强化Singleton属性(三)
来源:互联网 发布:mac 开发php 必备软件 编辑:程序博客网 时间:2024/06/06 04:52
1.饿汉式加载
类加载时就创建
public class MaYun {private static Mayun instance = new Mayun();private static getInstance() {return instance;}private MaYun() {//MaYun诞生要做的事情}public void splitAlipay() {System.out.println(“Alipay是我的啦!看你丫Yahoo绿眉绿眼的望着。。。”);}}
2.懒汉式加载
类使用时加载
public class MaYun {private static MaYun instance = null;private MaYun() {//MaYun诞生要做的事情}public static synchronized MaYun getInstance() {if (instance == null) {instance = new MaYun();}return instance;}public void splitAlipay() {System.out.println(“Alipay是我的啦!看你丫Yahoo绿眉绿眼的望着。。。”);}}
3.懒汉式的线程安全版(双重检验锁)
public class MaYun {private volatile static MaYun instance;private MaYun (){}public static MaYun getInstance() {if (instance == null) {synchronized (MaYun.class) {if (instance == null) {instance = new MaYun();}}}return instance;}}
在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗
4.静态内部类(推荐)
public class MaYun {private static class SigletonHolder {private static final instance = new MaYun();}public static final getInstance() {return SigletonHolder.instance;}private MaYun() {//MaYun诞生要做的事情}public void splitAlipay() {System.out.println(“Alipay是我的啦!看你丫Yahoo绿眉绿眼的望着。。。”);}Call:MaYun.getInstance().splitAlipay();
加载MaYun类时,在类的加载阶段把静态内部类加载了,也就是利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以这种方法非常推荐。
5.编写一个包含单个元素的枚举类型(极力推荐)
public enum MaYun {himself; //定义一个枚举的元素,就代表MaYun的一个实例private String anotherField;MaYun() {//MaYun诞生要做的事情//这个方法也可以去掉。将构造时候需要做的事情放在instance赋值的时候:/** himself = MaYun() {* //MaYun诞生要做的事情* }**/}public void splitAlipay() {System.out.println(“Alipay是我的啦!看你丫Yahoo绿眉绿眼的望着。。。”);}}Call:MaYun.himself.splitAlipay();
我们来认真分析一下这5种方法:
- 1234方法把构造器声明成私有的,但是这种方法是不能抵抗反射机制的攻击的!如下:
Constructor<?> constructor = MaYun.class.getDeclaredConstructors()[0];constructor.setAccessible(true);Elvis instance = (Elvis) constructor.newInstance();
依然可以创建一个对象!
解决的方法是添加计数器,大于1时抛出错误:
public class MaYun { private static AtomicInteger count = new AtomicInteger(0); private static final MaYun INSTANCE = new Elvis(); private MaYun() { if(count > 0) { throw new IllegalArgumentException("Cannot create Elvis twice"); } count.incrementAndGet() }
而方法5美剧方法可以防止反射攻击,当你试图通过反射去实例化一个枚举类型的时候会抛出IllegalArgumentException异常:
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:416) at org.effectivejava.examples.chapter02.item03.enumoration.MaYun.main(MaYun.java:21)
从这里看,方法5具有绝对的优势!
2.如果上面实现的Singleton是可以序列化的。那么方法1234加上implements Serializable只保证它可以序列化,为了保证反序列化的时候,实例还是Singleton,必须声明所有的实例域都是transient的,并且提供 readResolve方法,否则,每次反序列化都会生成新的实例。
但是方法5无偿提供了序列化机制,绝对防止多次实例化,又是绝对的优势!
这就是方法5值得极力推荐的的原因,同时jdk1.5以上才能使用的方法但是这种方法用的人太少了!!所以改变从你我开始!
阅读全文
0 0
- Effective Java之用私有构造器或者枚举类型强化Singleton属性(三)
- effective java(3) 之用私有构造器或者枚举类型强化Singleton属性
- Effective Java (3) - 用私有构造器或者枚举类型强化Singleton属性
- 《effective java》读书札记第三条用私有构造器或者枚举类型强化Singleton属性
- 用私有构造器或者枚举类型强化singleton属性——Effective Java 读书笔记
- Effective Java 学习 第三条 用私有构造器或者枚举类型强化Singleton属性
- Effective Java 2.3——用私有构造器或者枚举类型强化Singleton属性
- Effective Java -- 用私有构造器或者枚举类型强化Singleton属性
- Effective java第三条:使用私有构造器或者枚举类型强化Singleton属性
- 用私有构造器或者枚举类型强化 Singleton属性
- 用私有构造器或者枚举类型强化Singleton属性
- 用私有构造器或者枚举类型强化Singleton属性
- 用私有构造器或者枚举类型强化Singleton属性。
- 《Effective java》读书记录-第3条-用私有构造器或者枚举类型强化Singleton属性
- Java学习笔记3:用私有构造器或者枚举类型强化Singleton属性
- Java学习笔记3:用私有构造器或者枚举类型强化Singleton属性
- Effective java第三条:用私有构造器或者枚举类型强化singleon属性
- EffectiveJava-用私有构造器或者枚举强化Singleton属性
- How to get rid of this annoying W8123 warning in my IDE
- VUE优秀UI组件库合集
- Sqlserver2008连接失败的N种可能及解决方案
- Java中abstract class 和 interface 的解释和他们的异同点(转)
- pandas:填充缺失值 fillna("missing") 和fillna("missing",inplace=True)的区别
- Effective Java之用私有构造器或者枚举类型强化Singleton属性(三)
- [iOS11 + Xcode9 各大好文汇总]
- C#项目的IIS环境搭建
- Deep Reinforcement learning
- 多线程学习
- LeetCode(5) Longest Palindromic Substring解题报告
- 存储与服务器的连接方式对比(DAS,NAS,SAN)
- SJTUOJ1003路径法解决问题
- 数据挖掘十大经典算法——CART