《Effective Java讀書筆記》--序列化

謹慎地實現Serializable

實現Serializable有如下幾點風險

  • 實現Serializable的類一旦發佈,則「改變這個類的實現」的靈活性將大大下降。
  • 增長了錯誤和安全漏洞的可能性。
  • 測試負擔會增長。

爲了繼承而設計的類應該不多實現Serializable,接口也應該不多會擴展它。

保護性地編寫readObject方法

不嚴格的說,readObject是一個「用字節流做爲惟一參數」的構造函數"。因此在寫readObject時,就想象本身正在編寫一個構造函數。
例如,在一個類的構造函數中,對參數的有效性作了檢查,而且也作了保護性拷貝的話,readObject中也應該實現該邏輯。Period類(參考 http://my.oschina.net/u/1453800/blog/263037#OSC_h3_2)的readObject能夠寫成這樣:

private void readObject(ObjectInputStream s) throws IOException,
			ClassNotFoundException {
		s.defaultReadObject();
		start = new Date(start.getTime());
		end = new Date(end.getTime());

		if (start.compareTo(end) > 0) {
			throw new InvalidObjectException(start + "after" + end);
		}
	}



值得注意的是,這樣實現後,start和end都不能再定義成final了。不過下文會介紹readResolve方法,能夠做爲保護性readObject的替代選擇,而且保證start和end還能繼續定義成final。 java

在readObject中,不管是直接方式仍是間接方式,都不要調用類中可被改寫的方法。 安全

必要時提供一個readResolve方法

readResolve有兩個用法: 函數

  •  用來實現singletor的序列化
  • 做爲保護性的readObject方法的一種保守替代選擇,它的好處有:減小代碼冗餘,也不須要考慮太多細節;消除了「序列化對於使用final域的人爲限制」。

Peroid類的readResolve方法實現以下: 測試

private Object readResolve() throws ObjectStreamException {
		return new Period(start, end);
}
相關文章
相關標籤/搜索