我真的很佩服java功能,我不想放弃使用它来解决下一个问题:
我有一个可能被继承的类,其内部是private ArrayList arr;
所以setter函数没问题,但getter函数return arr;
返回对任何人都能编辑的变量的引用那个我不想要和私有的整个数组都没有任何意义!
在C ++中,我只是return const arr;
,它将返回对变量的常量引用。
我非常需要变量不被克隆或手动复制,因为有太多的计算要求(只读变量)为什么在java中没有返回const?有什么方法可以逃避复制吗?
p.s (final ArrayList<Integer> arr;)
不是一个选项,因为该数组总是会改变大小或元素值。
如果我找不到解决办法,我有可能回到C ++或公开一切,你永远不应该得到我的软件:D
答案 0 :(得分:23)
使用java.util.Collections.unmodifiableList包裹返回值。它不会复制数据,而是包装原始列表,并将只读操作委托给基础列表。修改列表的操作在运行时通过UnsupportedOperationException
被拒绝。
您
return arrayList;
变为
return Collections.unmodifiableList(arrayList);
不幸的是,编译器不会强制执行只读约束。但是,它们将在运行时强制执行。
您也可以使用:unmodifiableSet,unmodifiableMap,unmodifiableCollection,unmodifiableSortedSet和unmodifiableSortedMap。如果这些还不够,你仍然可以从这种通用设计方法中获取灵感,并创建自己的自定义只读包装类。
答案 1 :(得分:2)
:)你有几个选择:
不要公开getter,只提供允许调用的方法,例如
public void addToList(Object arg) { this.arr.add(arg);}
返回不可变对象:
public List getArr() { return Collections.unmodifiableList(this.arr); }
答案 2 :(得分:0)
你也可以使用Google Guava的不可变collections。在这种情况下,您可以在字段中存储ImmutableList。
当然,如果你的类需要在内部修改这个列表,那么使用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;
}
}
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
)。它还拒绝null元素。并且它不会复制源列表,如果它已经是一个ImmutableList,它可以避免无用的对象实例化。ImmutableList.of()
将字段初始化为空的ImmutableList,因为返回空集合而不是空值(Null Object pattern)是一种很好的做法。您可能认为这会创建不必要的对象实例化,但ImmutableList.of()
实际上会返回单例。答案 3 :(得分:0)
还有unmodifiableList方法的替代方法。您只需返回此私有数组的副本即可。例如,
return your_private_array.clone();
嗯,可能会有性能损失。但是你没有改变接口(你仍然返回一个数组)。
答案 4 :(得分:-1)
unmodifiableList绝对是答案。