2016-07-15 64 views
1

總是返回集合/對象字段的副本會是開銷嗎?在可變對象的getter中進行深度複製

+0

對不起,但「它會是開銷」顯然進入「給我你的意見」球場。從這個意義上說,你的問題不適合這裏。我的意見:這真的取決於。如果您的設計在返回副本的情況下效果更好,請執行此操作。如果各方都在處理**相同的**對象很重要,那麼也許您不會創建克隆。 – GhostCat

+0

半相關:http://stackoverflow.com/questions/19192762/inefficiency-of-defensive-copy-in-java – jaco0646

回答

1

確實存在開銷,但已經有一些框架類可以做到這一點。這也在有效的Java書中描述。

記住:

「類應該是一成不變的,除非有一個很好的理由讓他們可變....如果一個類不能進行能不變,限制了它的可變性儘可能地。」

當你想創建一成不變的類比你可以使用這樣的框架:http://immutables.github.io

有關示例檢查這個Oracle documentation

0

所有處理有成本。創建對象並初始化它們具有CPU和內存成本。 框架可以爲你做什麼,這是可能的,但如果你以一種方便的方式做到這一點,它不會降低這個成本。相反,如果手動執行,則兩個對象之間的映射屬性的性能會更好。 如果你注意表現,也許你應該研究是否可以避免深層複製。

2

顯然,是的,這將是一個開銷...與返回參考或淺拷貝相比。

但這不是重點。真正的意義在於開銷是否有保證/必要,以及是否可以通過使用其他數據結構/設計/技術來避免。這些問題的答案取決於上下文。


下面是一些例證:

  1. 如果目標對象的吸氣劑返回一個不可變的對象,副本是不必要的。例如,任何返回String的getter。
  2. 如果目標對象獲取器返回的對象不是目標對象抽象的一部分,則副本不受歡迎。示例list.get(int)Iterator.next()
  3. 如果目標對象的吸氣劑返回一個可變對象(或陣列)AND返回的對象是該對象的內部狀態的一部分AND目標不一定信任呼叫者,則吸氣劑要麼將它複製或包裹它......或者可能存在安全問題。
  4. 同樣可能適用於與安全無關的上下文;例如ArrayList.toArray(...)將列表複製到單獨的數組中,而不是返回列表的後備數組。 (類似於getChars()String,StringBuffer等)這就是保持抽象邊界,以便課堂上不會「破壞」另一個邊界。
  5. 如果目標對象的吸氣劑返回一個可變對象(或陣列)AND返回的對象是該對象的內部狀態的一部分BUT目標對象的API /抽象邊界設計爲「多孔」(例如出於性能的原因),那麼複製可能會自我失敗。

其中,3是唯一克隆是嚴格強制性的情況。在2,4和5中,你可能會爭辯說,這是你如何爲類,庫,應用程序設計公共(或內部)API的問題。往往有許多可行的選擇。

+0

@StephenC如果你需要在獲取器中克隆對象的時候可以舉一些例子,那將是非常好的可變對象 –