我真的很欣赏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 绝对是答案。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top