日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Effective Java之考虑自定义的序列化模式(七十五)

發布時間:2024/2/28 java 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Effective Java之考虑自定义的序列化模式(七十五) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么自定義序列化?

這里直接舉一個書上的例子

public final class StringList implements Serializable {private int size = 0;private Entry head = null;private static class Entry implements Serializable {String data;Entry next;Entry previous;}.... }

我們知道,序列一個類,會同時序列化它的組件
也就是說,如果我序列化了“B”對象, B是雙向鏈表,它要序列化它的內部成員“A”和“C”對象,但是序列化“A”和“C”對象的時候,B同時也是它們的組件,也要序列化“B”~~~~~~~~
于是就進入了無窮的死循環中!!!

這時候,我們的需求很簡單,對于每個對象的Entry,我只序列化一次就行了,不需要迭代序列化。
于是就有了transient關鍵字

public final class StringList implements Serializable {private static final long serialVersionUID = 1L;private transient int size = 0; //不會被序列化private transient Entry head = null;private static class Entry {String data;Entry next;Entry previous;}public final void add(String s) { ... }/*** Serialize this {@code StringList} instance* * @serialData The size of the list (the number of strings it contains)* is emitted ({@code int}), followed by all of its elements (each a * {@code String}), in the proper sequence.*/private void writeObject(ObjectOutputStream s) throws IOException {s.defaultWriteObject();s.writeInt(size);for(Entry e = head; e != null; e = e.next ) {s.writeObject(e.data);}}private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {s.defaultReadObject();int num = s.readInt();for(int i=0; i < num; i++) {add((String)s.readObject());}}..... }

標記為transient的不會自動序列化,這就防止默認序列化做出錯誤的事情,然后調用writeObject手動序列化transient字段,做自己認為正確的事。readObject同理。

注意??:盡管StringList的所有域都是transient,但writeObject和readObject的首要任務仍是調用defaultXxxObject方法來序列化不帶有transient的字段,這樣可以極大的增強靈活性。因為萬一以后加入了不帶有transient的字段呢?

總結,自定義序列化目的就是做自己認為正確的事情,經典的例子有ArrayList和HashMap。

自定義序列化的例子

ArrayList

來看一下關鍵的實例域:

private static final Object[] EMPTY_ELEMENTDATA = {};/*** Shared empty array instance used for default sized empty instances. We* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when* first element is added.*/private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};/*** The array buffer into which the elements of the ArrayList are stored.* The capacity of the ArrayList is the length of this array buffer. Any* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA* will be expanded to DEFAULT_CAPACITY when the first element is added.*/transient Object[] elementData; // non-private to simplify nested class access/*** The size of the ArrayList (the number of elements it contains).** @serial*/private int size;

這里定義空數組是為什么呢?
答案就在這里:Effective Java之返回零長度的數組或者集合,而不是null(四十三)

然后為什么transient Object[] elementData;
難道不應該初始化它的所有數組元素嗎?
原因就是ArrayList實際上是動態數組,每次在放滿以后自動增長設定的長度值,如果數組自動增長長度設為100,而實際elementData里面有可能有1個實際對象,其他都是null,默認的初始化會初始化99個null對象,這顯然不合適!
所以,我們來欣賞一下它的writeObject方法:

private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{// Write out element count, and any hidden stuffint expectedModCount = modCount;s.defaultWriteObject();// Write out size as capacity for behavioural compatibility with clone()s.writeInt(size);// Write out all elements in the proper order.for (int i=0; i<size; i++) {s.writeObject(elementData[i]);}//prevent concurrent modificationif (modCount != expectedModCount) {throw new ConcurrentModificationException();}}

HashMap

transient Node<K,V>[] table;

原因1

因為讀寫Map是根據Object.hashcode()來確定從table[i]讀/寫,而Object.hashcode()是native方法, 不同的JVM里可能是不一樣的。比如向HashMap存一個鍵值對entry, key為字符串"hello", 在第一個java程序里, "hello"的hashcode()為1, 存入table【1】在另一個JVM程序里, "hello" 的hashcode()有可能就是2, 存入table【2】所以不管物理結構,序列化只負責把key,value送貨上門,具體放在哪個table,序列化不需要理會。

原因2:

table 和 ArrayList的elementData 中存儲的值數量是小于數組的大小的(數組擴容的原因),這個在元素越來越多的情況下更為明顯。如果使用默認的序列化,那些沒有元素的位置也會被存儲,就會產生很多不必要的浪費。 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的Effective Java之考虑自定义的序列化模式(七十五)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。