2013-02-25 80 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