Collections.unmodifiableList(Arrays.asList(...)) 的替换
Replacement for Collections.unmodifiableList(Arrays.asList(...))
question.
的延续
我需要静态和公开将数据存储为数组,但我不需要希望有人修改我的数据。我只需要能够读取这些数组。因此,我认为我应该使用 C++ 中提供的 constant arrays 之类的东西。
据我了解,Collections.unmodifiableList(Arrays.asList(...))
阻止在 运行-time 修改列表,但在 compile-time.
我做了以下 class(代码已更新)。我想我 不是重新发明轮子 因为我无法使用 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
方法和其他一些方法
我测试了 class 并且它有效。
换句话说,如果我提供了我的库并且有人试图修改我的数据,我认为当 he/she 立即知道这是不可能的时候会更好(我的 class 没有方法来修改任何东西),如果我使用 unmodifiableList
he/she 只会注意到程序崩溃。
这个class的优缺点是什么?有没有办法改进这个class?
更新:
我决定采纳@Hoopje 的建议(查看答案)。它基于我没有的经验:我只是一个 Java 初学者。
如果 "reinventing the wheel" 还不够不利,我认为您的方法有一个主要缺点:
Arrays.asList
和 Collections.ummodifiableList
return List
实例,因此它们集成在 Java 集合框架中。这意味着您可以轻松地在增强的 for 循环 (for (E item : list) { }
) 中使用它们,作为流 (list.stream()
),使用所有 List
方法,将它们传递给需要 Collection
的方法或 List
subclasses 等
一个小问题是你的 class 复制了数组,而 Arrays.asList
和 Collections.ummodifiableList
return 观点都是他们的论点,所以他们没有复制数组。
顺便说一下,创建一个数组的浅拷贝不需要"magic":你可以做到
this.storage = storage.clone();
对 UPD1 的回答:
是的,不幸的是 Java 没有为无法修改的集合提供接口。因此,不可变的 List
实例将有一个 add(E)
方法,它只是抛出一个异常。所以没有编译时不变性保证。
但是,在您的方法的 Java 文档中,您当然会写 returned 列表是不可变的。如果您的库的用户测试 his/her 软件,他将非常确定地看到异常并意识到 he/she 出现了编程错误。
相信我,如果你剥夺了他们在基于集合的 API 中使用 returned 列表的可能性,你的图书馆的用户会非常讨厌你,只是为了没有任何的小优势看起来好像会修改它的方法。
question.
的延续我需要静态和公开将数据存储为数组,但我不需要希望有人修改我的数据。我只需要能够读取这些数组。因此,我认为我应该使用 C++ 中提供的 constant arrays 之类的东西。
据我了解,Collections.unmodifiableList(Arrays.asList(...))
阻止在 运行-time 修改列表,但在 compile-time.
我做了以下 class(代码已更新)。我想我 不是重新发明轮子 因为我无法使用 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
方法和其他一些方法
我测试了 class 并且它有效。
换句话说,如果我提供了我的库并且有人试图修改我的数据,我认为当 he/she 立即知道这是不可能的时候会更好(我的 class 没有方法来修改任何东西),如果我使用 unmodifiableList
he/she 只会注意到程序崩溃。
这个class的优缺点是什么?有没有办法改进这个class?
更新:
我决定采纳@Hoopje 的建议(查看答案)。它基于我没有的经验:我只是一个 Java 初学者。
如果 "reinventing the wheel" 还不够不利,我认为您的方法有一个主要缺点:
Arrays.asList
和 Collections.ummodifiableList
return List
实例,因此它们集成在 Java 集合框架中。这意味着您可以轻松地在增强的 for 循环 (for (E item : list) { }
) 中使用它们,作为流 (list.stream()
),使用所有 List
方法,将它们传递给需要 Collection
的方法或 List
subclasses 等
一个小问题是你的 class 复制了数组,而 Arrays.asList
和 Collections.ummodifiableList
return 观点都是他们的论点,所以他们没有复制数组。
顺便说一下,创建一个数组的浅拷贝不需要"magic":你可以做到
this.storage = storage.clone();
对 UPD1 的回答:
是的,不幸的是 Java 没有为无法修改的集合提供接口。因此,不可变的 List
实例将有一个 add(E)
方法,它只是抛出一个异常。所以没有编译时不变性保证。
但是,在您的方法的 Java 文档中,您当然会写 returned 列表是不可变的。如果您的库的用户测试 his/her 软件,他将非常确定地看到异常并意识到 he/she 出现了编程错误。
相信我,如果你剥夺了他们在基于集合的 API 中使用 returned 列表的可能性,你的图书馆的用户会非常讨厌你,只是为了没有任何的小优势看起来好像会修改它的方法。