返回数组列表的 const 引用
-
27-09-2019 - |
题
我真的很欣赏java的特性,并且我不想放弃使用它来解决下一个问题:
我有一个可能被继承的类,里面有一个 private ArrayList arr;
所以setter函数没问题,但是getter函数 return arr;
返回对该变量的引用,任何能够编辑我不想要的整个数组的人都没有任何意义!
在 C++ 中我只会 return const arr;
并且它将返回对该变量的常量引用。
我非常需要不要克隆或手动复制变量,因为有很多计算需要(只读变量)为什么在java中没有const返回???有什么办法可以避免复制吗?
附注 (final ArrayList<Integer> 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); }
你也可以使用 谷歌番石榴是不可变的 收藏品. 。在这种情况下,您将存储一个 不可变列表 在你的领域。
当然,如果你的类需要在内部修改这个列表,使用 ImmutableList 可能 事实证明这是一个坏主意,因为您需要创建一个新的 ImmutableList 实例并每次将其重新分配给该字段......
但当您知道 List 在对象构造后不会更改时,它就完美了。
不可变示例(对象构造后列表不会更改)
@Immutable
public final class Foo {
@Nonnull
private final ImmutableList<String> list;
public Foo(@Nonnull List<String> list) {
// you could also compute the appropriate list here
// before assigning it to the field
this.list = ImmutableList.copyOf(list);
}
public ImmutableList<String> getList() {
return list;
}
}
可变示例(列表只能使用 setter 修改)
public class Foo {
@Nonnull
private ImmutableList<String> list = ImmutableList.of();
public ImmutableList<String> getList() {
return list;
}
public void setList(@Nonnull List<String> list) {
this.list = ImmutableList.copyOf(list);
}
}
评论
- 我知道通常建议让方法返回尽可能最通用的类型(
List
在本例中),但我更喜欢将 getter 的返回类型声明为ImmutableList
, ,因为它充当文档(无需在 Javadoc 中记录返回列表的不变性)和 API 契约。这就像说“我 保证 该列表是不可变的,您不必担心或防御性地复制它”。而且非常简洁。 ImmutableList.copyOf()
很棒,因为它会自动拒绝空列表(通过抛出NullPointerException
)。它还拒绝空元素。如果源列表已经是 ImmutableList,它不会复制源列表,这避免了无用的对象实例化。- 在第二个示例中,我使用以下命令将该字段初始化为空的 ImmutableList
ImmutableList.of()
, ,因为返回空集合而不是空值是一个很好的做法(空对象模式)。您可能认为这会创建不必要的对象实例化,但是ImmutableList.of()
实际上返回一个单例。
有是将unmodifiableList方法的替代方法。你可以只返回这个私人数组的一个副本。例如,
return your_private_array.clone();
那么,有可能是这样的性能损失。但你必须接口不变(您仍返回阵列)。
unmodifiableList 绝对是答案。