首页 > 编程语言 >【Java】序列化与单例

【Java】序列化与单例

时间:2022-11-11 12:05:40浏览次数:42  
标签:Java 单例 java io new catch import 序列化


之前明白了 线程安全且延迟加载的单例如何写,有两种,双重检验和静态内部类。然后为了防止反射破坏单例,在私有构造方法里面加入了一个同步变量的判断,确保构造方法只调用一次。但是仍然无法阻止序列化破坏单例,例子:

package gggg;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class S implements Serializable {

private S(){
System.out.println("con");
}
static class SS{
private static S s = new S();

}

public static S instance(){
return SS.s;
}
public static void main(String[] args) {
try {
S s1 = S.instance();
FileOutputStream out = new FileOutputStream("a");
ObjectOutputStream outt = new ObjectOutputStream(out);
outt.writeObject(s1);

FileInputStream in = new FileInputStream("a");
ObjectInputStream inn = new ObjectInputStream(in);
S s2 = (S) inn.readObject();
System.out.print(s1 == s2);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

可以看到这里是false,说明有两个实例。

在readObj底层实现上,是通过反射调用私有构造方法来返回实例的,但是在这段代码后面,还会检测该类是否有一个readResolve()方法,如果有,就返回这个方法返回值。这个方法必然是为了解决序列化破坏单例的,我们可以添加这个方法,让其返回单例。

所以在单例类中添加如下方法:

public Object readResolve(){
return instance();
}


最后再执行,就是true了,说明返回了同一个对象。


标签:Java,单例,java,io,new,catch,import,序列化
From: https://blog.51cto.com/u_15873544/5844102

相关文章

  • 【Java】HashMap 实现原理
    Java集合框架有两个顶级接口,一个是collection接口,另一个是map接口,hashmap便是map接口的重要实现类。首先看map接口。根据map键值对的特性,接口中必然有相关的方法,主要是:Vget......
  • 【Java】concurrentHashMap
    concurrentHashMap类引入了段的概念,读操作不需要上锁,写操作只需要获取相应的段的锁即可,而非锁定全部的数据。所以map里面是一个segment的数组,segment里面才是entry的数组。m......
  • 【Java】Map 实现类
    hashmap:遍历时顺序无法保证linkedhashmap:遍历时按照插入顺序treemap:遍历时按照大小顺序linkedhashmap实现上是继承了hashmap,多了一个双向的链表记录插入顺序,重写了迭代器,基......
  • 【Java】 Set实现类
    Set是collection的子接口,对应数学中的集合。与list的最主要的区别是,set无法通过索引取值,因为set是无序的。set还有一个特性是唯一性,不能存相同的元素。第一个实现类是hashse......
  • 【Java】垃圾回收机制 GC
    GC是java中比较有特色的技术,减轻了程序员的负担。当然也是面试中的高频话题。对于垃圾回收,首先要解决的是找出哪些对象是需要回收的。第一个方法是计算引用数目,实现比较简单......
  • springboot 引入外部包的坑Lookup method resolution failed; nested exception is ja
    手动引入jar包<dependency><groupId>com.allinpay.sdk</groupId><artifactId>top-sdk-java</artifactId><version>1.0.5</......
  • java
    Java是一种编程语言和计算平台,由SunMicrosystems在1995年首次发布。它从微末起步,逐渐发展为当今数字世界中很大一部分资产所依赖的基础,是用于构建许多服务和应用程序......
  • Java之找不到或无法加载主类
    IDEA报错:错误:找不到或无法加载主类。解决方法1:原因:未能成功编译。尝试:菜单栏Build->RebuildProdject 解决方法2:原因:IDEA缓存问题。尝试:菜单栏File->Invalida......
  • Java--comparator接口与Comparable接口的区别
    1.Comparator和Comparable相同的地方他们都是java的一个接口,并且是用来对自定义的class比较大小的,什么是自定义class:如publicclassPerson{Stringname;int......
  • Java实现算法之--选择排序
        选择排序也是比较简单的一种排序方法,原理也比较容易理解,它与冒泡排序的比较次数相同,但选择排序的交换次数少于冒泡排序。冒泡排序是在每次比较之后,若比较的两个......