这基本上是对 question 的后续从昨天。我试图实现“最通用的方式”(我能想到的)以构建“真正的”不可修改的集合。下面的代码工作正常;但它需要抑制警告(“rawtypes”和“unchecked”)。
我尝试了各种方法来避免这些警告;但根本找不到替代方案。所以,我的问题是:是否有一种干净的方法来避免我抑制的警告?
(我看到了另一个 question ;但我不能 100% 确定它是否真的适用于我的代码;因为我不确定我是否可以在不使用原始类型的情况下写下“Generator”接口(interface))。
private interface Generator<T> {
T generateNewInstance();
}
@SuppressWarnings("rawtypes")
private final static Generator ListGenerator = new Generator<List>() {
@Override
public List generateNewInstance() {
return new ArrayList();
}
};
public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
@SuppressWarnings("unchecked")
List<T> newInstance = makeNewInstanceOf(elements.getClass(), ListGenerator);
newInstance.addAll(elements);
return Collections.unmodifiableList(newInstance);
}
private static <T> T makeNewInstanceOf(Class<T> incomingClass, Generator<T> fallbackGenerator) {
try {
return (T) incomingClass.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
return fallbackGenerator.generateNewInstance();
}
}
最佳答案
如果您复制 List<T>
进入一个新的ArrayList<T>
, 并将该引用内联传递给 Collections.unmodifiableList
,除了不可修改的装饰器之外,没有其他任何东西可以访问副本来修改它:
List<String> original = new ArrayList<>(Arrays.asList("Hello", "World"));
// This simply decorates original, so updates to original are
// reflected in this list.
List<String> unmodifiableDecorator = Collections.unmodifiableList(original);
// The reference to the new ArrayList is scoped to the call to
// Collections.unmodifiableList, so nothing else can have a
// reference to it.
List<String> unmodifiableCopy =
Collections.unmodifiableList(new ArrayList<>(original));
System.out.println("Before clear:");
System.out.println(original);
System.out.println(unmodifiableDecorator);
System.out.println(unmodifiableCopy);
original.clear();
System.out.println("After clear:");
System.out.println(original);
System.out.println(unmodifiableDecorator);
System.out.println(unmodifiableCopy);
输出:
Before clear:
[Hello, World]
[Hello, World]
[Hello, World]
After clear:
[]
[]
[Hello, World]
所以 unmodifiableCopy
没有被修改,也不能被修改,除非你能以某种方式说服 unmodifiableList
向您提供委托(delegate)引用。
因为您不能修改它,所以您不需要使副本与输入列表具有相同的具体列表类型。只需将其设为 ArrayList
,因为它几乎具有 List
可以实现的最佳读取性能实现。
所以你的方法,没有警告或额外的类,可以是:
public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
return Collections.unmodifiableList(new ArrayList<>(elements));
}
关于java - 使用 "raw types"作为静态字段/返回类型时如何避免泛型警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36768707/