为什么 UnaryFunction<Object> 可以转换为 UnaryFunction<T>?

Why UnaryFunction<Object> can be casted to UnaryFunction<T>?

当我阅读Effective Java第27条时,UnaryFunction<Object>和[=15之间的类型转换=] 把我弄糊涂了。

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 是 class。在这种情况下,列表中的元素可能是 A 的超类型,因此这种转换是不合理的,因此编译器不允许这样做。在函数 (UnaryFunction<Object>) 的情况下,暗示这可以 return 一个对象。假设您的代码是 IDENTITY = t -> new Object();,在这种情况下转换为 UnaryFunction<A> 是不合理的,因为它 return 是 Object。在 UnaryFunction<T> 的情况下,有一些类型 T 满足转换,也就是说,当 TObject.

有关这方面的一些背景阅读,请参阅:Liskov substitution principle 处理函数的子类型。