返回arraylist的const引用

我真的很佩服javafunction,我不想放弃使用它来解决下一个问题:

我有一个可能被inheritance的类,并且它内部是一个private ArrayList arr; 所以setter函数没问题,但是getter函数return arr; 返回对该变量的引用,任何人都能够编辑我不想要的整个数组,私有没有任何意义!

在C ++中,我只return const arr; 它会返回对变量的常量引用。

我非常需要变量不被克隆或手动复制,因为有太多的计算需要(只读变量)为什么在java中没有返回const? 有什么方法可以逃避复制吗?

ps (final ArrayList arr;)不是一个选项,因为该数组总是更改大小或元素值。

如果我找不到解决方法,我威胁要回到C ++或公开一切,你永远不应该得到我的软件:D


编辑:一个更重要的问题:我是否要求一些不好的东西(软件工程明智)我的意思是如果JAVA创建者认为没有const引用(返回只读引用)那么我必须要求可以在其他地方处理的东西办法。 或者我的程序设计错了我很困惑。

使用java.util.Collections.unmodifiableList包装返回值。 它不会复制数据,而是包装原始列表,并将只读操作委托给基础列表。 将在运行时通过UnsupportedOperationException拒绝修改列表的操作。

您的

 return arrayList; 

 return Collections.unmodifiableList(arrayList); 

遗憾的是,编译器不会强制执行只读约束。 但是,它们将在运行时强制执行。

您也可以使用: unmodifiableSet , unmodifiableMap , unmodifiableCollection , unmodifiableSortedSet和unmodifiableSortedMap 。 如果这些还不够,您仍然可以从这种通用设计方法中获取灵感,并创建自己的自定义只读包装类。

:)你有几个选择:

  • 不要暴露getter,只提供允许调用的方法,例如

    public void addToList(Object arg) { this.arr.add(arg);}

  • 返回不可变对象:

    public List getArr() { return Collections.unmodifiableList(this.arr); }

您还可以使用Google Guava的不可变集合 。 在这种情况下,您将在您的字段中存储ImmutableList 。

当然,如果你的类需要在内部修改这个列表,那么使用ImmutableList 可能会成为一个坏主意,因为你需要创建一个新的ImmutableList实例并每次都将它重新分配给字段……

但是当你知道List在对象构造之后不会改变时,它是完美的。

不可变的例子(对象构建后列表不会改变)

 @Immutable public final class Foo { @Nonnull private final ImmutableList list; public Foo(@Nonnull List list) { // you could also compute the appropriate list here // before assigning it to the field this.list = ImmutableList.copyOf(list); } public ImmutableList getList() { return list; } } 

可变示例(列表只能使用setter修改)

 public class Foo { @Nonnull private ImmutableList list = ImmutableList.of(); public ImmutableList getList() { return list; } public void setList(@Nonnull List list) { this.list = ImmutableList.copyOf(list); } } 

备注

  • 我知道经常建议让方法返回尽可能最通用的类​​型(在本例中为List ),但我更喜欢将我的getter的返回类型声明为ImmutableList ,因为它充当了文档(不需要记录返回列表的不变性) Javadoc)和API合同。 这就像说“我保证这个列表是不可变的,你不必担心或防御性地复制它”。 它非常简洁。
  • ImmutableList.copyOf()很棒,因为它会自动拒绝空列表(通过抛出NullPointerException )。 它还拒绝null元素。 如果它已经是一个ImmutableList,它将不会复制源列表,这避免了无用的对象实例化。
  • 在第二个示例中,我使用ImmutableList.of()将字段初始化为空的ImmutableList,因为返回空集合而不是空值( Null对象模式 )是一种很好的做法。 您可能认为这会创建不必要的对象实例化,但ImmutableList.of()实际上会返回一个单例。

还有unmodifiableList方法的替代方法。 您只需返回此私有数组的副本即可。 例如,

  return your_private_array.clone(); 

那么,可能会有性能损失。 但是你的接口没有变化(你仍然返回一个数组)。

unmodifiableList绝对是答案。

Interesting Posts