我知道泛型类型和参数化类型之间的一般区别,并且我知道一些一般规则:
但我的问题有点具体。所以我要给出一些代码。
根据上述一般规则,以下2个例子中的cast是无效的:
static List<String> f1a(List<String> list) {
return List.of((String[]) list.toArray()); // ClassCastException
}
static List<String> f2a(List<String> list) {
return (List<String>) List.of(list.toArray()); // compile-time error: Inconvertible types
}
现在,如果我用泛型类型参数 E 替换 String 类型,则转换有效!但我真的不明白为什么?// f1 is a generic version f1a, where String -> E
static <E> List<E> f1(List<E> list) {
return List.of((E[]) list.toArray());
}
// f2 is a generic version f2a, where String -> E
static <E> List<E> f2(List<E> list) {
return (List<E>) List.of(list.toArray());
}
下面的演示显示 f1 和 f2 是有效的,而 f1a 和 f2a 有问题:public static void main(String[] args) {
List<String> list = List.of("hello", "world");
List<String> copy1 = f1(list); // works
System.out.println(copy1);
List<String> copy2 = f2(list); // works
System.out.println(copy2);
List<String> copy1a = f1a(list); // ClassCastException
System.out.println(copy1a);
List<String> copy2a = f2a(list); // compile-time error
System.out.println(copy2a);
}
最佳答案
f1
由于类型删除而起作用。投到E[]
在运行时被完全删除,这意味着你的代码在运行时会表现得像这样,但它确实让编译器推断你正在返回 List<E>
而不是 List<Object>
,因此让程序编译。
static List f1(List list) {
return List.of(list.toArray());
}
f2
由于基本相同的原因而起作用。这次是List.of(list.toArray())
的结果推断为 List<Object>
因为 toArray
返回 Object[]
,但后来被删除的类型转换使它编译。f1a
有一个 ClassCastException
因为你想转 Object[]
成String[]
.在 Java 中,数组甚至在运行时都知道它们声明的类型,因此 toArray
返回的数组认为自己是一个 Object[]
即使它真的只持有字符串并且不喜欢变成 String[]
.f2a
不起作用,因为您无法转动 List<Object>
成List<String>
.如果要将列表转换为字符串数组,请尝试
list.toArray(new String[0])
.这样,它将返回一个正确的 String[]
并且不会引起问题。如果您转换
List<Object>
到 List<String>
,使用 (List) List.of(list.toArray())
转换为原始类型
关于java - Java 中的泛型类型转换与参数化类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62645840/