学习这条首先要了解什么是Singleton,Singleton就是仅仅被实例化一次的类,我们先来看一个常见的单例:
public class Singleton { public final static Singleton INSTANCE = new Singleton(); private Singleton(){ } }
这样的单例其实并不能完全保证该类只被实例化一次,攻击者可以通过反射获得私有的构造器,并执行setAccessible(true)方法使其能够被访问,这就破坏了单例只能被实例化一次的特性。解决这个问题就是在私有的构造器中判断被执行的次数,不是第一次执行时候就抛出异常。
还有一种情况是有的单例需要被序列化,即实现java.io.Serializable接口。单例的对象被反序列化时就会创建新的实例。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton.txt")); oos.writeObject(Singleton.INSTANCE); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton.txt")); Singleton sin = (Singleton)ois.readObject();
这里的sin就是一个新的实例,解决这个问题需要将单例中所有非基本类型的域都加transient修饰符,表明这些域都不需要被序列化,同时要在类中加入readResolve方法返回唯一的实例:
private Object readResolve(){ return INSTANCE; }
这样就能保证反序列化得到的对象也是那个唯一的实例,至于为什么会在后面序列化的章节专门有一条做阐释。
通过上面的分析过程,大家会发现实现一个完美的单例太复杂了,幸运的是,JDK1.5之后,我们有了更好的方式来实现单例,那就是枚举类型:
public enum EnumSingleton{ INSTANCE; }
这种方法再简单不过了,不需要考虑反射攻击的情况,而且无偿地提供了序列化机制,绝对防止多次实例化,所以在以后实现单例的时候优先地考虑枚举吧!
相关推荐
- **副作用**:使用私有构造器的一个副作用是使得该类不能被继承。 **避免创建不必要的对象**: 1. **不可变对象**:对于不可变对象,可以通过缓存已创建的对象来避免重复创建。 2. **使用静态工厂方法**:如果一...
#### EJ 第3条:用私有构造器或枚举类型强化Singleton属性 单例模式是一种常用的软件设计模式,旨在确保一个类只有一个实例,并提供一个全局访问点。Kotlin通过`object`关键字进一步简化了单例模式的实现,使得创建...
Java中的枚举类型是线程安全的,并且只会装载一次,设计者充分考虑到了线程安全问题,因此使用枚举实现单例模式是一种简洁而且高效的解决方案。 6. 容器式单例(Singleton Holder) 通过一个私有的静态内部类...
1. **避免反射攻击**:在私有构造器中添加条件判断,如`if (instance != null)`,这样即便反射尝试创建新实例也会被阻止。 2. **避免反序列化攻击**:为单例类实现`readResolve()`方法,确保即使反序列化也不会创建...
- 构造器私有化,防止其他类通过new关键字创建实例。 - 创建并保存该类的唯一实例,通常使用静态变量存储。 - 提供一个公共的静态方法或属性,以便外部获取这个唯一的实例。 常见的单例实现方式有以下几种: - **...
即当前类所在路径及其引用的第三方类库的路径,如第四节中的问题6所述)下的类库 加载到内存中。 开发者可以直接使用系统类加载器。 5. 设计模式:(框架中使用,是程序设计的高级思想) 1. 单例模式...
- **枚举方式**:利用枚举类型天然的线程安全性和唯一性实现单例模式,简洁高效。 #### 五、单例模式的适用场景 单例模式适用于以下情况: - 系统只需要一个实例对象时。 - 单例对象需要被共享,并且所有的实例...
而“singleton method.txt”很可能是讲解或展示了不同类型的单例实现方式,包括传统的单例模式和基于枚举的单例实现。 通过深入学习和实践这三个主题,你将能更好地理解和掌握Java的核心特性,以及在实际项目中如何...
- 使用`Integer.parseInt()`等方法将字符串转换为基本类型。 4. **Object类** - 所有类的父类。 - 定义了一些公共方法,如`toString()`、`equals()`等。 5. **代码块** - 用于初始化对象的代码块。 - 构造...
•总之,第一步先找局部变量,第二步,内部类的属性,第三步。外部类的属性。 本文原创作者:pipi-changing 本文原创出处:http://www.cnblogs.com/pipi-changing/ 静态内部类 •如果用...
3. **系统必须能够访问该实例**:通常情况下,单实例模式会提供一个静态方法或者属性,以便外部代码能够获取到这个唯一的实例。 #### 单实例模式的应用场景 在软件开发中,单实例模式有着广泛的应用,比如打印机...
1. **私有构造器**: 单例类的构造器通常被声明为`private`,这样其他类无法通过`new`关键字直接创建该类的实例。这是防止外部代码实例化单例对象的第一道防线。 2. **静态内部类**: 在上述例子中,单例对象`...
在Java中,`switch`语句可以作用于`byte`、`short`、`char`、`int`类型,也可以作用于枚举类型和字符串(从Java 7开始)。 #### 第三十二题:Singleton模式的实现 Singleton模式确保一个类只有一个实例,并提供一...
第三十,switch不能作用于byte,但Java 7开始可以作用于char和枚举类型。Java 14引入了switch表达式,可以作用于String。 第三十一,编写Singleton模式的代码,一种常见方式是饿汉式(静态初始化)或懒汉式(双检锁...
1. **私有构造器(Private Constructor)**:这是最常用的控制对象创建的方式,特别是用于实现单例模式。通过将类的构造器声明为私有,外部类无法直接实例化它。例如: ```java public class Singleton { private ...
- 使用String类提供的`valueOf()`方法或基本类型的`toString()`方法进行转换。 4. **Object类** - Object是所有Java类的根类,提供了一些基本方法。 5. **代码块** - 代码块用于初始化对象的某些部分。 6. **...
23. 构造器不能被 override,因为构造器具有与类相同的名称,且不能有返回类型。 24. 不能直接继承 String 类,因为String是final的。 25. 当一个线程进入synchronized方法后,其他线程无法进入该对象的其他...
- 单例模式确保一个类只有一个实例,通常通过私有构造器、静态工厂方法或双检锁实现。 以上是针对Java面试中常见的问题的详细解答,涵盖了类、对象、集合、异常处理、并发等多个方面,这些知识对于理解和编写高...
例如,对于饿汉式单例模式,可以通过反射强制调用私有构造器或通过序列化-反序列化来创建新实例。为解决这些问题,可以采用枚举类型实现单例模式,或者在懒汉式的基础上进行优化,比如在类中加入防止反射创建实例的...