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); } ? }
以上就是小編今天的分享了,希望可以幫助到大家。