在JDK1.5之前的单例实现方式有两种(懒汉式和饿汉式并无设计上的区别故看做一种),两者同是私有构
造器,导出静态成员变量,以便调用者访问。
第一种
package singleton;
public class Singleton {
//导出全局成员
public final static Singleton INSTANCE = new Singleton();
//私有构造
private Singleton(){}
}
私有构造器只会被调用一次,用于构建Singleton类中的INSTANCE 实例,由于构造器被私有化,并且没
有其他公开的构造器,所有能够保证在app中只会有一个Singleton实例。
真的是我们想的那样只会存在一个么?答案是否定的,可以使用java反射包提供的setAccessible()
方法去掉权限检查即可构造出实例对象
使用反射构造单例对象
final Constructor<?>[] constructors = Singleton.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
//忽略检查
constructor.setAccessible(false);
//构造对象实例
final Object newInstance = constructor.newInstance();
System.out.println(newInstance == Singleton.INSTANCE); //false
}
现在单例类被反射轻松攻破了吧。
再看第二种基于工厂方法的单例
package singleton;
public class Singleton {
//导出全局成员
private final static Singleton INSTANCE = new Singleton();
//私有构造
private Singleton(){}
public static final Singleton getInstance(){
return INSTANCE;
}
}
该方式与第一种差别并不大,工厂方法的优势在于灵活性,在不改变API的前提下,我们可以修改该类
是否为单例,还是为每一个线程构建一个实例对象。同第一中方式相同也存在反射攻击的可能性,为了
防止反射攻击,需要对私有构造进行改写
package singleton;
import java.lang.reflect.Constructor;
public class Singleton {
//导出全局成员
public final static Singleton INSTANCE = new Singleton();
//私有构造
private Singleton(){
if (null != INSTANCE) {
throw new IllegalArgumentException("不能存在两个实例对象");
}
}
public static void main(String[] args) throws Exception {
final Constructor<?>[] constructors = Singleton.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
//忽略检查
constructor.setAccessible(false);
//构造对象实例 此时这里回抛出异常
final Object newInstance = constructor.newInstance();
System.out.println(newInstance == Singleton.INSTANCE);
}
}
这样子也可以就可以保证不受反射的攻击啦。
在JDK1.5之后的版本提供了枚举关键字,提供了更加方便的单例创建方式
public enum Singleton {
INSTANCE;
}
三句代码搞定一个单例,并且无偿的提供序列化机制,绝对防止多实例的存在。
以上两种方式如果序列化,仅仅是实现serialiazble接口是不够的,为了维护和保证Singleton请提供
一个方法
public Singleton redResolve(){
return INSTANCE;
}
分享到:
相关推荐
通过单例模式,我们可以控制类的实例化过程,避免这些问题。 实现单例模式,Java中有几种常见的方法: 1. 饿汉式(静态常量):这是最简单的实现方式,它在类加载时就完成了初始化,因此是线程安全的。代码如下: ...
这个模式在Java中尤其常见,因为Java的垃圾回收机制允许对象长时间驻留在内存中,使得单例模式能够有效地管理资源。 在单例模式中,类的实例化过程被控制,防止了多线程环境下的多个实例产生,从而避免了潜在的共享...
在Java编程中,单例模式是一种常用的创建型设计模式,它保证了类只有一个实例,并提供一个全局访问点。单例模式常用于管理共享资源,如配置文件的读取。本篇将详细介绍如何利用枚举(enum)来实现单例模式,并结合`...
在C#中,实现单例模式有多种方法,下面将详细讲解五种常见的实现方式。 1. 饿汉式(Static Singleton): 这是最简单也是最直接的实现方式。在类加载时就初始化了单例,线程安全且避免了同步开销。代码如下: ```...
在Java编程中,单例模式常用于管理共享资源,如数据库连接池、线程池或者配置信息等,以提高效率并减少系统内存开销。这个小练习适合初学者来学习和理解单例模式的基本概念和实现方式。 单例模式的关键在于限制类的...
单例模式的关键在于限制类的实例化,防止多个实例的存在。 在Java中实现单例有多种方法,下面详细讨论给定文件中提到的五种方式: 1. **懒汉式(非线程安全)**: 这种实现方式延迟初始化,只有在第一次调用`...
单例模式是一种在软件设计中常见的设计模式,它的核心目标是确保一个类只有一个实例,并提供一个全局访问点。在Java等面向对象编程语言中,单例模式常用于控制资源的共享,如全局配置、数据库连接池、日志服务等。...
在日志工具类的场景中,单例模式的应用尤为恰当,因为它避免了因频繁创建日志对象而导致的内存浪费。 原始的日志工具类`LogUtil`提供了一个简单的日志级别控制功能,通过静态方法`debug`, `info`, `error`根据预设...
在Java中,单例模式的应用广泛,尤其是在处理系统级服务、配置信息、线程池等需要全局共享的对象时。下面我们将深入探讨单例设计模式的实现方式和注意事项。 1. **饿汉式单例** 饿汉式单例在类加载时就完成了实例...
单例模式是一种非常实用的设计模式,可以有效地管理和控制系统的资源。不同的实现方式各有优缺点,选择合适的实现方式需要根据具体的应用场景和需求来决定。在实际开发过程中,应充分考虑线程安全性和延迟加载的需求...
**设计模式——单例模式** 在软件工程中,设计模式是一种在特定场景下解决常见问题的标准方案,可以被复用并提升代码质量。单例模式是设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。这种模式...
总的来说,单例模式是设计模式中的一种基础模式,它在软件开发中广泛应用,能帮助我们更好地管理和控制对象的生命周期。不过,过度依赖单例也可能导致设计过于紧密,不利于单元测试和解耦,因此在使用时需要权衡利弊...
在多线程环境中,单例模式尤其关键,因为它可以保证多个线程安全地共享同一实例,避免资源浪费和并发问题。本文将详细介绍四种常见的Java单例设计模式:饿汉式、懒汉式、Holder方式和枚举方式。 1. **饿汉式** ...
Java实现单例设计模式方法解析 单例设计模式是软件设计模式中的一种,旨在确保一个类只有一个实例,并提供一个全局访问点。Java中有多种方式可以实现单例设计模式,本文将对这些方法进行解析,并提供示例代码。 一...
单例设计模式是一种在软件设计中广泛使用的设计模式,它保证了一...在实际开发中,合理使用单例模式,结合其他设计模式,可以提高代码的可读性和可维护性,但也要注意避免滥用,以防止引入不必要的复杂性和潜在的问题。
Java中的单例设计模式是一种确保一个类只有一个实例并提供一...综上所述,单例模式在Java中有着多种实现方式,每种方式都有其优缺点。选择哪种实现取决于特定的需求,如性能、线程安全、序列化以及反序列化时的行为等。
单例模式是软件设计模式中的经典模式之一,其主要目的是控制类的实例化过程,确保在应用...在设计模式中,单例模式不仅限于上述实现,还可以与其他模式结合使用,如工厂模式、装饰器模式等,以达到更灵活、高效的设计。
单例模式是软件设计模式中的一种经典模式,它在许多场景下被广泛使用,尤其是在需要全局唯一实例的情况下。本文将深入探讨单例模式的概念、作用、实现方式以及其在实际编程中的应用。 单例模式的核心思想是确保一个...
**设计模式——单例模式** 单例模式是一种广泛应用于软件设计中的创建型设计模式,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。这样做的好处在于控制共享资源的访问,比如线程安全的数据库连接池...
单例模式是软件设计模式中的一种经典模式,用于确保一个类只有一个实例,并提供一个全局访问点。在Java中,有多种实现单例模式的方法,每种都有其特点和适用场景。接下来,我们将深入探讨这些实现方式。 首先,我们...