【问题标题】:Deep copying in getters for mutable object [closed]可变对象的getter中的深度复制[关闭]
【发布时间】:2016-07-15 10:29:20
【问题描述】:

总是返回集合/对象字段的副本是否会产生开销?

【问题讨论】:

  • 抱歉,但“会不会是开销”显然属于“给我你的意见”的范畴。从这个意义上说,你的问题不适合这里。我的意见:这真的取决于。如果您的设计在返回副本后效果更好,那么就这样做。如果所有各方都在处理相同对象很重要,那么也许您不创建克隆。

标签: java oop


【解决方案1】:

显然,是的,与返回引用或浅拷贝相比,这将是一个开销。

但这并不是重点。真正的重点是开销是否有保证/必要,以及是否可以通过使用其他一些数据结构/设计/技术来避免。这些问题的答案取决于上下文。


这里有一些插图:

  1. 如果目标对象 getter 返回不可变对象,则不需要复制。例如,任何返回 String 的 getter。
  2. 如果目标对象 getter 返回的对象不是目标对象抽象的一部分,则不需要复制。例如list.get(int)Iterator.next()
  3. 如果目标对象 getter 返回一个可变对象(或数组)AND返回的对象是对象内部状态的一部分AND目标不一定信任调用者,那么 getter 应该复制或包装它……否则可能存在安全问题。
  4. 这同样适用于非安全相关的上下文;例如ArrayList.toArray(...) 将列表复制到单独的数组中,而不是返回列表的支持数组。 (getChars()StringStringBuffer 等类似)这完全是为了维护抽象边界,以便在课堂上不会“破坏”另一个抽象边界。
  5. 如果目标对象 getter 返回一个可变对象(或数组)AND返回的对象是对象内部状态的一部分但是目标对象的 API/抽象边界是设计为“多孔”(例如出于性能原因),那么复制可能会弄巧成拙。

其中,只有 3 个是严格强制进行克隆的情况。在 2、4 和 5 中,您可能会争辩说,这是您如何为类、库、应用程序设计公共(或内部)API 的问题。而且通常有很多可行的选择。

【讨论】:

  • @StephenC 如果你能举一些例子,在可变对象的 getter 中克隆对象是必要的,那就太好了
【解决方案2】:

这肯定是开销,但已经有一些框架类可以做到这一点。 《Effective Java》一书中也对此进行了描述。

记住:

“类应该是不可变的,除非有很好的理由让它们可变......如果一个类不能成为不可变的,请尽可能限制它的可变性。”

当您想要创建不可变类时,可以使用这样的框架:http://immutables.github.io

例如检查这个Oracle documentation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 2018-01-28
    • 2012-02-26
    • 1970-01-01
    • 2012-12-15
    • 2013-03-11
    • 2023-03-17
    相关资源
    最近更新 更多