Collections.unmodifiableList(Arrays.asList(...))的替换

时间:2018-01-06 18:57:26

标签: java arrays immutability

question的延续。

我需要将静态公开存储数据作为数组,但我不希望有人修改我的数据。我只需要从这些数组中读取数据。因此我认为我应该使用C ++中提供的常量数组之类的东西。

据我所知Collections.unmodifiableList(Arrays.asList(...))阻止在运行时修改列表,但不能在编译时修改列表。

我已经完成了以下课程(代码已更新)。我想我没有重新发明轮子因为我使用unmodifiableList得不到相同的结果。

/**
 * Emulates constant arrays from C++.
 *
 * @param <E> Type of elements. Has to be immutable type.
 */
public final class ConstArray<E> {

    /** Stores elements. */
    private final E[] storage;

    /**
     * Constructs the object.
     *
     * @param storage   Elements.
     */
    public ConstArray(final E[] storage) {
        this.storage = storage.clone();
    }

    /**
     * Returns element at {@code idx}.
     *
     * @param idx   Index of returning element.
     * @return      Element at {@code idx}.
     */
    public final E get(final int idx) {
        return storage[idx];
    }
}

省略size方法和其他一些方法。

我已经对课程进行了测试,但它确实有效。

要解释一下,如果我提供我的图书馆并且有人试图修改我的数据,我认为当他/她立刻知道它不可能时会更好(我的班级不会这样做)有一个方法来修改任何东西)如果我使用unmodifiableList他/她将注意到程序崩溃。

这门课的优点和缺点是什么?有没有办法改善这个班级?

UPD:

我决定使用@Hoopje的建议(见答案)。它基于我没有的经验:我只是一个Java初学者。

1 个答案:

答案 0 :(得分:2)

如果“重新发明轮子”不够缺点,我认为你的方法有一个主要的缺点:

Arrays.asListCollections.ummodifiableList返回List个实例,因此它们集成在Java Collections框架中。这意味着您可以在增强型for循环(for (E item : list) { })中轻松使用它们,作为流(list.stream()),使用所有List方法,将它们传递给期望Collection的方法或List子类等。

一个小问题是,您的类会复制数组,而Arrays.asListCollections.ummodifiableList都会返回其参数的视图,因此它们不会复制数组。

顺便说一下,创建数组的浅表副本不需要“魔术”:你可以做

this.storage = storage.clone();

回答UPD1:

是的,遗憾的是Java没有为无法修改的集合提供接口。因此,不可变的List实例将具有例如仅抛出异常的add(E)方法。因此,不存在编译时保证不变性。

但是,在您的方法的Javadoc中,您当然会写出返回的列表是不可变的。如果您的图书馆用户测试他/她的软件,他将非常确定地看到异常并意识到他/她编程错误。

相信我,你的图书馆用户会非常讨厌你,如果你拿走他们在基于收集的API中使用返回列表的可能性,只是因为没有任何方法看起来好像他们会修改它。