2013-02-25 72 views
7

考虑UnaryFunction界面中定义的有效的Java泛型章节。为什么安全地抑制这种未经检查的警告?

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。但是身份识别功能是特殊的:它 返回未经修改的参数,所以我们知道无论T的值如何使用 它作为UnaryFunction<T>是类型安全的。因此,我们可以自信地压制 这个强制转换生成的未经检查的强制转换警告。一旦我们完成了这些工作,代码将会编译时不会出现错误或 警告。

+0

旁边的问题:你在用什么书,是否说这个代码的重点是什么? – asteri 2013-02-25 17:00:45

+0

@Jeff有效的java是书名,它在泛型章节中有介绍,特别是在描述泛型函数的章节中。 – Geek 2013-02-25 17:11:32

回答

3

演员是安全insomuch仅作为身份的函数返回传递给它摆在首位的确切对象。因此,在运行时,通用参数T没有专门化可以违反演员表。

也就是说,您正在投射一个对象,因为它是自己的类型。

3

有了类型擦除

T apply(T arg); 

实际上是

Object apply(Object arg); 

现在的身份

Abc x = ...; 
Abc y = IDENTITY.apply(x); 

可以假设它始终是正确的(相当于y = x;)。

(很务实。)

+0

在代码中调用'apply'在哪里? – Geek 2013-02-25 17:01:04

+0

每当应用identityFunction(.apply)时,结果将被分配为 T IDENTITY.apply(T),通常无法完成,因为参数的T在运行时不存在。 – 2013-02-25 17:44:47

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)中,返回类型与输入类型相同的证明在实现中。我们返回相同的实例,因此它保证具有相同的类型。当您禁止类型安全警告时,建议使用证明来证明它的正确性。

+0

-1令人困惑。 IdentityFunction()不返回“函数本身”,它返回_argument_本身。我看不出为什么这个结果,类型T是“用于不同的对象”。在你的例子中,它是一个String,它不能用于不同的对象。 – user949300 2013-02-25 17:41:07

+1

@ user949300:'identityFunction()'返回存储在变量'IDENTITY_FUNCTION'中的对象的引用。该引用允许你调用'apply()',因此'identityFunction()'有效地返回函数本身。如果名字不一样,会更好。例如'getIdentityFunction()'和'IDENTITY_FUNCTION'。答案的第一行是引用getter方法。 – unholysampler 2013-02-25 17:53:38

+0

谢谢 - 理解。整个问题/系统对于什么都不做的事情是非常困惑的:-)。尽管由于StackOverflow的局限性,我无法“撤销”我的downvote,直到您编辑您的答案为止。 – user949300 2013-02-25 18:49:57

相关问题