我正在阅读 Joshua Bloch 的 Effective Java 第二版,第 25 项(第 122 页)。当您进一步阅读本章时,您会看到作者编写了以下代码:
// Naive generic version of reduction - won't compile!
static <E> E reduce(List<E> list, Function<E> f, E initVal) {
E[] snapshot = list.toArray(); // Locks list
E result = initVal;
for (E e : snapshot)
{
result = f.apply(result, e);
}
return result;
}
然后作者声明编译器不会编译它,因为您需要在赋值 E[] snapshot = list.toArray();
所在的行添加一个显式转换,结果在这个 E[] snapshot = (E[]) list.toArray();
上,在这之后你会得到一个警告说有 [unchecked ] 未经检查的转换
。
问题 1:我知道这本书考虑到了 Java 6 之前的变化(我们现在差不多是 Java 8)。但是,我写了同样的方法,从编译中得到了同样的错误。这是因为我需要添加显式转换。但是没有警告。那么这个警告是关于什么的?
问题 2:作者声明以下方法可行,但事实证明它不是类型安全。
With minor modifications, you could get it to throw a
ClassCastException
on a line that doesn't contain an explicit cast.
好的,我明白了...但是我怎样才能让它抛出 ClassCastException
?
我在这篇文章中留下了一个准备运行的例子,如果你想自己检查一下:
import java.util.Arrays;
import java.util.List;
public class Main
{
public static void main(String[] args)
{
List<Integer> ints = Arrays.asList(10,20,30);
Integer result = reduce (ints,new Function<Integer>() {
@Override
public Integer apply(Integer arg1, Integer arg2)
{
return arg1 + arg2;
}
},0);
System.out.println(result);
}
static <E> E reduce(List<E> list, Function<E> f, E initVal)
{
E[] snapshot = (E[]) list.toArray(); // Locks list
E result = initVal;
for (E e : snapshot)
{
result = f.apply(result, e);
}
return result;
}
interface Function<T>
{
public T apply(T arg1, T arg2);
}
}
最佳答案
E[] snapshot = list.toArray();
list.toArray()
返回 Object[]
而不是 E[]
。所以你需要在那里进行显式转换。但是这样的显式(或动态)转换的存在意味着编译器无法保证那里的类型安全。相反,您是在告诉编译器一切正常,并且在运行时它实际上是一个 E[]
。因此,它会警告您 - unchecked cast。请注意,如果编译器能够保证那里的类型安全,那么它将在那里进行静态/检查转换(由编译器本身隐式执行)。
关于java - Effective Java - Item 25 - Generics class cast exception 混合列表和数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23713350/