.
.
不算完美, 但是比较实用, 所以比较推荐
一般程序员不太会去调用Class.forName(), 也就不会触发new实例
.
线程安全, 但是会有长期的性能问题 ( 每次调用getInstance方法, 都会涉及加锁操作 )
.
解决了初始化完成之后, 性能下降的问题, 只有在初期, 代码才会进入synchronized
但是仍然有可能会有多个线程进入synchronized同步代码块, 每次进去, 都会new一个实例, 所以也是有问题的
最主要的缺点就是太复杂
第一个判空是有必要的, 可以阻止很多线程一上来就去获取锁, 这样就又退回到前一个解法了
.
在内部类里给instance直接赋值, 静态内部类必须是private的
加载外部类的时候, 不会加载内部类, 这样就实现了懒加载
加载指的是Class.forName, 但由于程序员一般不会使用Class.forName, 所以更推荐第一种写法
JVM能保证加载一个类, 只会加载一次, 所以只会new一次
java创始人之一, 在Effective Java一书中的推荐
但是也有缺点: 写起来别扭, 还是用class写起来比较顺, 定义成enum总感觉写逻辑不太舒服
.
在项目中最推荐用第一种写法, 最简单好记, 线程安全
首先程序员一般不会去调用Class.forName去加载它, 所以只是看上去像饿汉, 实际上却和懒汉差不多
另外, 程序员更不会去用反射故意去new第二个对象, 这种故意搞破坏不在考虑范围之内
第六种写法太复杂, 要记得细节点特别多, 而且也没法阻止反射的方法
第七种写法相对简单, 比第一种还是有些复杂, 而且也没法阻止反射的方法
第八种写法在语法上是完美的, 简单, 线程安全, 防止反射, 就是写起来别扭
.