用这种方式实现单例,绝对能加分!

简介: 单例这个东西,可是说是Java基础面试必考问题,不管大小公司,提问率极高,有的面试官甚至直接让你写出具体的代码实现。所以,搞清楚单例的实现并且懂得接下来所说的,绝对能够让面试官对你有更好的印象。

就像强哥在上篇推文说的《Effective Java 第三版》 含Java8、Java9内容,今天我们就开始Effective Java之旅。

单例这个东西,可是说是Java基础面试必考问题,不管大小公司,提问率极高,有的面试官甚至直接让你写出具体的代码实现。所以,搞清楚单例的实现并且懂得接下来所说的,绝对能够让面试官对你有更好的印象。

Singleton(单例)就是指程序从运行开始到结束,仅仅被实例化一次的类。比如数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

单例的通常有一下两种方法,很简单,记下来一般就都忘不了。第一种方法,共有静态成员是final域:

public class QiangGe{  public static final QiangGe INSTANCE = new QiangGe();  private QiangGe(){    …… //具体的一些初始化操作  }}


这种方式调用的时候,直接通过QingGe.INSTANCE属性就能够获取到唯一的类实例。

第二种方法,共有成员是个静态工厂方法:

public class QiangGe{private static final QiangGe INSTANCE = new QiangGe();private QiangGe(){    …… //具体的一些初始化操作  }  public static QiangGe getInstance(){    return INSTANCE;  }}


这种方式调用的时候,直接通过QingGe.getInstance()方法就能够获取到唯一的类实例。

第一种方法的优势在于简单,而且很容易让你看出来这个类是个单例。而第二种方法的优势在于它更灵活,在不改变API的前提下,我们可以改变getInstance方法的实现来改变该类是否应该是单例的想法,如在实现中改成每个线程返回唯一的类实例。另外,在Java8中,这种工厂方式也可以直接通过方法引用作为提供者:QiangGe::getInstance就是一个提供者Supplier<QiangGe>。

不过,需要提到的一点也是面试官经常会问到的一点就是,按上面的方式,是否有方法在程序中生成两个类实例。答案是有的,一般可以通过反射或者反序列化的方式来做到这种方式。


  • 反射:借助反射中的AccessibleObject.setAccessible方法,通过反射来生成新的类实例。
  • 反序列化:如果该类实现了Serializable接口,则每次反序列化一个序列化实例时,都会创建一个新对象。

避免上面的问题的解决方法:


  • 反射:可通过修改构造器,让他在需要创建第二个实例时抛异常。
  • 反序列化:需要在类中添加readResolve方法,readResolve方法作用是:当JVM从内存中反序列化地"组装"一个新对象时,就会自动调用 readResolve方法来返回我们指定好的对象:

private Object readResolve(){  return INSTANCE;}


好了,上面就是我们一般也比较常用的单例实现了。可是其实还有一种方法更简单好用,面试提一提没准就能加分。那就是枚举了。

public enum QiangGe{  INSTANCE;}


这种方法与上面的第一种方法相似,单更加简洁,且无偿的提供了序列化机制,绝对防止上面通过反射和序列化在程序中获取到过个实例的情况发生。虽然这种方法还没有推广,用的人也比较少,但是单元素枚举类型经常成为实现单例的最佳方式。

好了,这些就是在Effective Java中有提到的对单例的实现机制建议。强哥之前在面试中遇到问及单例的问题,都会替代着说一句”通过枚举类型实现单例会更好……“。面试官回应的也都是比较满意的表情拉~

相关文章
|
6月前
|
消息中间件 安全 Java
面试官:单例Bean一定不安全吗?实际工作中如何处理此问题?
面试官:单例Bean一定不安全吗?实际工作中如何处理此问题?
103 5
|
6月前
|
安全 Java 数据库
给大忙人写的单例模式的八种实现方法
给大忙人写的单例模式的八种实现方法
55 0
|
5月前
|
Java Apache Spring
面试官:如何自定义一个工厂类给线程池命名,我:现场手撕吗?
【6月更文挑战第3天】面试官:如何自定义一个工厂类给线程池命名,我:现场手撕吗?
38 0
|
存储 算法 编译器
【C++技能树】再也不怕没有对象了 --初识类
我们先来看看C语言解决一个问题的过程。
71 0
|
设计模式 C#
C# 机房重构单例模式
C# 机房重构单例模式
69 0
|
设计模式 SQL 安全
【设计模式学习笔记】单例模式详解(懒汉式遇上多线程问题解析基于C++实现)
【设计模式学习笔记】单例模式详解(懒汉式遇上多线程问题解析基于C++实现)
348 0
【设计模式学习笔记】单例模式详解(懒汉式遇上多线程问题解析基于C++实现)
|
设计模式 安全 算法
单例模式的十种写法,你会几个?
单例模式是一种最常见的设计模式,写法也比较多,在这篇文章里面主要是对单例模式的各种写法进行一个介绍。面试的时候会对其中两三种进行体会,而且我还遇到了口述单例模式的例子。重要性就不言而喻了吧。
198 0
单例模式的十种写法,你会几个?
|
存储 安全 Java
static关键字真能提高Bean的优先级吗?答:真能(下)
static关键字真能提高Bean的优先级吗?答:真能(下)
static关键字真能提高Bean的优先级吗?答:真能(下)
|
Java 中间件 程序员
static关键字真能提高Bean的优先级吗?答:真能(上)
static关键字真能提高Bean的优先级吗?答:真能(上)
static关键字真能提高Bean的优先级吗?答:真能(上)
|
安全 Java 编译器
单例模式 的那点儿事儿
单例模式 的那点儿事儿
99 0