java resolve是什么?让我们一起来了解一下吧!
原理:
反序列化时,首先获取序列化的类 : desc( 可理解为单例类的class类,但它和JVM加载到内存中的单例class类有不同)因为如果我们的单例类在构造方法中通过实例不为空则抛出异常防止了反射破坏单例,那单例类是不允许再实例化的。而desc类却依然可以实例化。(当我们反序列化一个对象时,永远不会调用其类的构造函数,反序列化后的实例变量与序列化之前的实例变量相同,类变量与当前的类变量相同,如果反序列化时类未被加载则类变量为默认值。)
判断对象是否能实例化。可以则进行实例化,至此单例类进行了第一次实例化,对象名为obj。第一次实例化完成后,通过反射寻找该单例类中的readResolve()方法,没有则直接返回obj对象。有定义readResolve()方法,desc通过invokeReadResolve(Object obj)方法调用readResolve()方法获取单例对象instance,将他赋值给rep,如果单例对象之前已经被实例化过,那么rep就会指向之前实例化的单例对象。如果我们之前没有实例化单例对象,则rep会指向null。
rep与obj进行比较,由于obj是反射获取的对象,当然与rep不等,于是将rep的值instance赋值给obj,将obj返回,返回对象instance也就保证了单例。
java resolve是从序列化中恢复一个单例对象会破坏单例模式,解决方法是添加readResolve() :通过反序列化readObject()方法获取对象时会去寻找readResolve()方法,如果该方法不存在则直接返回新对象,如果该方法存在则按该方法的内容返回对象,以确保如果我们之前实例化了单例对象,就返回该对象。如果我们之前没有实例化单例对象,则会返回null。
实战演练,具体步骤如下所示:
package com.singleton; import java.io.ObjectStreamException; import java.io.Serializable; /** * 懒汉单例设计模式案例 */ public class SingletonDemo implements Serializable { /** * 懒加载 */ private static SingletonDemo instance; /** * 私有构造器 */ private SingletonDemo() { // 防止通过反射实例对象而跳过getInstance()方法 if (instance != null) { throw new RuntimeException("Object has been Instance !!!"); } } /** * 调用方法才加载类,资源利用率高了,但要保证线程安全 */ public static synchronized SingletonDemo getInstance() { if (instance == null) { instance = new SingletonDemo(); } return instance; } /** * 提供readResolve()方法 * 当JVM反序列化恢复一个新对象时,系统会自动调用readResolve()方法返回指定好的对象 * 从而保证系统通过反序列化机制不会产生多的Java对象 * * @return 单例对象 * @throws ObjectStreamException 异常 */ private Object readResolve() throws ObjectStreamException { return instance; } } package com.singleton; import org.junit.Test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * 单例测试类 */ public class SingletonTest { /** * 测试方法 */ @Test public void test() throws Exception { // 获取instance对象 SingletonDemo instance = SingletonDemo.getInstance(); // 获取文件输出流 FileOutputStream fileOutputStream = new FileOutputStream("E:\\Test.txt"); // 获取对象输出流 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); // 输出对象 objectOutputStream.writeObject(instance); // 关闭资源 objectOutputStream.close(); fileOutputStream.close(); // 获取对象输入流 ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("E:\\Test.txt")); // 读取对象 Object object = objectInputStream.readObject(); // 判断两个对象是否相等,返回true/false System.out.println(instance == object); } }
以上就是小编今天的分享了,希望可以帮助到大家。