【问题标题】:Return immutable copy of mutable object from method从方法返回可变对象的不可变副本
【发布时间】:2014-04-16 16:03:32
【问题描述】:

我有一些封闭的组件正在处理一些 XML 对象。我需要在这个组件之外公开这个对象,但我不想允许在我的组件之外对其进行更改。我怎样才能完成这个?

【问题讨论】:

  • 创建类及其所有字段final。这样你可以一次创建对象并初始化所有字段,你将无法修改属性。

标签: java immutability


【解决方案1】:

确保您的对象有一个copy constructor,它允许您制作您的类的深度克隆副本。

然后在返回对象时调用它,例如

SomeClass instance = // ....


public SomeClass getInstance() {
  return new SomeClass(instance);
}

这不会使返回的对象不可变。但这并不需要 - 您只是不希望外部代码更改您的数据副本。

【讨论】:

  • 接受的解决方案更像这里建议的。我刚刚从类对象创建了新对象并从方法中返回它。
  • 返回可变对象的语义有点混乱,因为不清楚该对象是否可以安全地被视为供应商拥有的对象的视图,作为独立于供应商的新对象,或两者都不是。如果该方法返回一个新实例,我更愿意在名称中明确说明。
【解决方案2】:

好吧,这里是访问级别的倡导者;-)

如果您只是希望阻止调用者进行更改,这并不意味着它必须是不可变的 [在您的包中] - 它只是意味着它不应该有 [ public] 改变它的方法 :) 实际上,我越来越喜欢返回 限制性公共接口

例如:

// Option A with a "limiting public interface"
public interface Awesome {
    public String getText();
}

class MyAwesome implements Awesome {
    public String getText() {
       // ..
    }
    // Option B is to make setText non-public
    public void setText() {
       // ..
    }
}

然后您的代码可以返回 Awesome,它不会 [直接] 提供改变对象的方法。

【讨论】:

  • +1 我倾向于忘记这种模式,但我也开始喜欢它了。
  • 这种方法的一个困难是它没有向调用者提供关于是否可以将返回的对象作为保持其状态的一种方式进行持久化的指示。
【解决方案3】:

我认为您需要创建另一个不可变的类,将您的对象作为参数(可能在构造函数中)。那么你应该只公开你的新类的实例。

以下是使对象不可变的一些技巧:Immutable class?

【讨论】:

  • "那你应该只暴露你的新类的实例" > 你能解释一下这句话吗?
  • 当然,提问者需要公开一个对象:"I need to expose this object outside of this component"。我告诉他/她应该创建另一个不可变的类,创建该新类的实例并公开该新创建的对象而不是他想要公开的对象。
猜你喜欢
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多