考虑 Effective Java 泛型章节中定义的UnaryFunction
接口。
public interface UnaryFunction<T> {
T apply(T arg);
}
以及以下用于返回UnaryFunction
// Generic singleton factory pattern
private static UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() {
public Object apply(Object arg) { return arg; }
};
// IDENTITY_FUNCTION is stateless and its type parameter is
// unbounded so it's safe to share one instance across all types.
@SuppressWarnings("unchecked")
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) IDENTITY_FUNCTION;
}
为什么IDENTITY_FUNCTION
到(UnaryFunction<T>)
的演员阵容安全?
这本书说的是我要问的问题,但我不能遵循这里的逻辑。我们在哪里调用执行身份操作的apply
函数?我很困惑,因为它是一个函数,它返回传递给它的同一个对象,而不修改任何东西。
将IDENTITY_FUNCTION投射到
(UnaryFunction<T>)
会生成一个 未经检查的投射警告,因为UnaryFunction<Object>
不是 每个UnaryFunction<T>
T
。但身份功能是特殊的:它 返回其参数未修改,因此我们知道它是使用的类型安全 无论UnaryFunction<T>
的价值如何,它都是T
。因此,我们可以 自信地抑制由生成的未经检查的强制转换警告 这个演员。一旦我们完成了这个,代码编译没有错误或 警告。
答案 0 :(得分:3)
使用类型擦除
T apply(T arg);
实际上是
Object apply(Object arg);
现在为身份
Abc x = ...;
Abc y = IDENTITY.apply(x);
可以假设它总是正确的(相当于y = x;
)。
(非常务实。)
答案 1 :(得分:3)
演员阵容是安全的,只有身份函数返回首先传递给它的 完全 对象。因此,在运行时,通用参数T
没有可以违反演员表的专门化。
Aka,你正在投射一个对象,因为它是自己的类型。
答案 2 :(得分:1)
identityFunction()只返回函数本身,用于不同的对象。
以下是一个用法示例:
String result = identityFunction().apply("Hello");
类型安全警告很重要。它就在那里,因为实现了IDENTITY_FUNCTION,使得编译器不能保证函数返回与输入相同的类型。 考虑以下替代实现:
private static UnaryFunction<Object> CONST_FUNCTION = new UnaryFunction<Object>() {
public Object apply(Object arg) { return "Default"; }
};
此实现始终返回一个字符串,因此将其作为一般数据类型的一元函数返回显然是不安全的。
在我们的例子中(IDENTITY_FUNCTION),返回类型与输入类型相同的证明在实现中。我们返回相同的实例,因此保证它们具有相同的类型。当您取消类型安全警告时,建议使用证明来证明它。