代码之家  ›  专栏  ›  技术社区  ›  Ismail Marmoush

返回arraylist的常量引用

  •  15
  • Ismail Marmoush  · 技术社区  · 14 年前

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

    我有一个可以继承的类,其中有一个 private ArrayList arr; 所以setter函数没问题,但是getter函数 return arr; 返回对该变量的引用,任何人都可以编辑我不想要的整个数组,而private没有任何意义!

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

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

    附笔 (final ArrayList<Integer> arr;) 不是选项,因为数组总是更改大小或元素值。

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


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

    5 回复  |  直到 7 年前
        1
  •  23
  •   Mike Clark    14 年前

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

    你的

    return arrayList;
    

    变成

    return Collections.unmodifiableList(arrayList);
    

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

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

        2
  •  2
  •   andbi    14 年前

    :)您有几个选项:

    • 不要公开getter,只提供允许调用的方法,例如。

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

    • 返回不可变对象:

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

        3
  •  0
  •   Etienne Neveu    13 年前

    你也可以用 Google Guava 的不可变 collections . 在这种情况下,您将存储 ImmutableList 在你的领域。

    当然,如果您的类需要在内部修改此列表,请使用ImmutableList 可以 结果证明这是个坏主意,因为您需要创建一个新的ImmutableList实例,并每次将其重新分配给字段。。。

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

    不可变示例(对象构造后列表不会更改)

    @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.of() ,因为返回空集合而不是空值是一个很好的做法( Null Object pattern ). 您可能认为这会创建不必要的对象实例化,但是 不可变列表() 实际上返回一个单重态。
        4
  •  0
  •   CS Pei    11 年前

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

        return your_private_array.clone();
    

    好吧,这可能会有表演上的惩罚。但是接口没有改变(仍然返回一个数组)。

        5
  •  -1
  •   fastcodejava    14 年前

    unmodifiableList 绝对是答案。