提问人:AntonBoarf 提问时间:11/14/2023 更新时间:11/14/2023 访问量:54
Java:强制转换和泛型
Java : casting and generics
问:
我对泛型有一些理解问题
我有这个变量:private static final UnaryOperator<Object> IDENTITY_FN = t -> t;
我不明白为什么这段代码会编译:
public static <T> UnaryOperator<T> identityFunction() {
return (UnaryOperator<T>) IDENTITY_FN;
}
UnaryOperator<String> fn = identityFunction();
但。。。此代码不编译:
UnaryOperator<String> fn = (UnaryOperator<String>) IDENTITY_FN;
对我来说,它看起来基本是一样的
答:
我认为在第二个代码片段中,它没有编译,因为强制转换为是不安全的,因此不允许编译。是安全的,因为它使用类型擦除,允许它使用泛型类型。由于类型擦除,投射是安全的。在运行时,Java 类型系统会擦除类型变量 T,并将其替换为其绑定变量或 Object(如果它是无界的)。因此,在运行时,只需 变成 ,并且可以安全地转换为此原始类型。UnaryOperator<String>
identityFunction()
(UnaryOperator<T>) IDENTITY_FN
UnaryOperator<T>
UnaryOperator
IDENTITY_FN
当您将结果分配给特定类型的变量(如 )时,Java 编译器会检查这些类型是否兼容。identityFunction()
UnaryOperator<String>
在编译时不允许将表达式(类型为 )转换为类型,因为可以证明某些东西不可能同时是 a 和 a(即不能有任何类型是两者的子类型)。泛型类型参数是不变的,因此 虽然是 的子类型,但不是 的子类型,反之亦然。如果一个实现类继承了两次,则不允许在两次继承中使用不同的类型参数继承它。IDENTITY_FN
UnaryOperator<Object>
UnaryOperator<String>
UnaryOperator<Object>
UnaryOperator<String>
String
Object
UnaryOperator<String>
UnaryOperator<Object>
UnaryOperator
另一方面,在编译时不允许将 (which has type ) 转换为 type,因为某些东西有可能同时是 a 和 a ——也就是说,如果 是 ,那么将是两者的子类型。尽管此强制转换也可能不正确(即何时是 ),但由于至少有一种情况可能是有效的,编译器不能禁止它。IDENTITY_FN
UnaryOperator<Object>
UnaryOperator<T>
UnaryOperator<Object>
UnaryOperator<T>
T
Object
UnaryOperator<Object>
T
Object
评论
UnaryOperator<T>
UnaryOperator<String>