15

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

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

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

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

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

如果我找不到解决方案,我威胁要回到 C++ 或公开所有内容,你永远不应该得到我的软件:D


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

4

4 回答 4

23

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

您的

return arrayList;

变成

return Collections.unmodifiableList(arrayList);

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

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

于 2010-11-24T00:31:36.443 回答
2

:) 你有几个选择:

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

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

  • 返回不可变对象:

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

于 2010-11-24T00:49:37.923 回答
0

您还可以使用Google Guava的不可变集合。在这种情况下,您将在您的字段中存储一个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;
    }
}

可变示例(列表只能使用 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()很棒,因为它会自动拒绝空列表(通过 throwing NullPointerException)。它还拒绝空元素。如果它已经是一个ImmutableList,它不会复制源列表,这样可以避免无用的对象实例化。
  • 在第二个示例中,我使用 将字段初始化为空的 ImmutableList ImmutableList.of(),因为返回空集合而不是空值(空对象模式)是一种很好的做法。您可能认为这会创建不必要的对象实例化,但ImmutableList.of()实际上返回的是单例。
于 2011-03-19T13:14:26.323 回答
-1

unmodifiableList绝对是答案。

于 2010-11-24T01:52:09.633 回答