当我阅读有效的Java 项目27时,UnaryFunction<Object>
和UnaryFunction<T>
之间的类型转换使我感到困惑。
interface UnaryFunction<T> {
T apply(T t);
}
public class Main {
private static final UnaryFunction<Object> IDENTITY = new UnaryFunction<Object>() {
public Object apply(Object t) {
return t;
}
};
@SuppressWarnings("unchecked")
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) IDENTITY;
}
public static void main(String ... args) {
UnaryFunction<A> identityA = Main.identityFunction();
A a = identityA.apply(new A());
}
}
class A {}
为什么可以将
UnaryFunction<Object>
强制转换为UnaryFunction<T>
? 我知道通用类型将在编译器后删除。因此
(UnaryFunction<T>) IDENTITY
最终将是(UnaryFunction<Object>) IDENTITY
,它将在运行时中运行。但是编译器不允许直接将
UnaryFunction<Object>
转换为UnaryFunction<A>
。UnaryFunction<A> identityA = (UnaryFunction<A>)IDENTITY;
//incompatible types: UnaryFunction<java.lang.Object> cannot be converted to UnaryFunction<A>
而且
UnaryFunction<Object>
和UnaryFunction<T>
之间没有继承关系。那么为什么可以将UnaryFunction<Object>
强制转换为UnaryFunction<T>
? 最佳答案
由于类型擦除,所有无限制的通用类型(... extends ...
都被视为Object
。因此,此强制转换可能对T
的某些值有效。 @SuppressWarnings("unchecked")
告诉编译器您在做正确的事情,因此该警告被禁止。
强制转换为特定类型是有问题的。假设您要处理的List<Object>
转换为List<A>
,其中A
是一个类。在这种情况下,list可能具有A
的父类(super class)型的元素,因此这种转换是不正确的,因此编译器不允许这样做。如果是函数(UnaryFunction<Object>
),则暗示它可以返回一个Object。假设您的代码是IDENTITY = t -> new Object();
,在这种情况下,由于返回UnaryFunction<A>
,因此对Object
的转换会不正确。在UnaryFunction<T>
的情况下,存在某种类型的T
可以满足转换要求,即T
是Object
时。
有关此内容的一些背景知识,请参见:Liskov substitution principle,它处理函数的子类型化。