Java单例模式面试题
引言
在Java开发中,单例模式是一种常见的设计模式。它用于确保一个类只有一个实例,并且提供了全局访问该实例的方式。在面试过程中,面试官经常会问一些关于单例模式的问题,以评估面试者对设计模式的理解和应用能力。本文将介绍几个常见的单例模式面试题,并提供相应的代码示例。
问题1:如何实现懒汉式单例?
懒汉式单例是指在第一次调用获取实例的方法时才创建实例。以下代码示例展示了一种懒汉式单例的实现方式:
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
// 私有构造方法,防止外部创建实例
}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
在上述代码中,instance
变量是私有的,并且通过getInstance()
方法进行获取。在第一次调用getInstance()
方法时,会创建一个LazySingleton
实例并赋值给instance
变量。由于使用了synchronized
关键字,可以保证在多线程环境下的线程安全性。但是,由于每次调用getInstance()
方法都需要获取锁,这种实现方式在性能上并不高效。
问题2:如何实现双重检查锁定的单例?
为了提高懒汉式单例的性能,可以使用双重检查锁定(Double-Checked Locking)来实现。以下代码示例展示了一种双重检查锁定单例的实现方式:
public class DoubleCheckedSingleton {
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {
// 私有构造方法,防止外部创建实例
}
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
在上述代码中,instance
变量使用了volatile
关键字修饰,确保了在多线程环境下的可见性。通过双重检查的方式,在第一次调用getInstance()
方法时进行同步,避免了每次调用都需要获取锁的开销,提高了性能。
问题3:如何实现饿汉式单例?
饿汉式单例是指在类加载时即创建实例,以保证只有一个实例存在。以下代码示例展示了一种饿汉式单例的实现方式:
public class EagerSingleton {
private static EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
// 私有构造方法,防止外部创建实例
}
public static EagerSingleton getInstance() {
return instance;
}
}
在上述代码中,instance
变量在类加载时即被创建,并且通过getInstance()
方法进行访问。由于在类加载过程中只会实例化一次,因此可以保证只有一个实例存在。
问题4:如何防止反射破坏单例模式?
通过反射可以访问和修改私有构造方法,从而破坏单例模式的实现。为了防止这种破坏,可以在构造方法中添加判断,当已有实例存在时抛出异常。以下代码示例展示了一种防止反射破坏单例的实现方式:
public class Singleton {
private static Singleton instance;
private Singleton() {
if (instance != null) {
throw new RuntimeException("Singleton instance already exists.");
}
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在上述代码中,当已有实例存在时,在构造方法中抛出运行时异常。这样,在尝试通过反射创建实例时,会