2013-08-28 73 views
1

我想使用無界通配符,因爲我有一些Callable的返回一個對象,但我對該對象不感興趣(他們返回null,我只是使用Callable而不是Runnable來能夠拋出檢查異常)。正確使用無界wilcard的泛型

所以在原則上我想這樣做:

CompletionService<?> ecs = ... 
Callable<?> = ... 
Future<?> f = ecs.submit(c); 

但在這裏我得到一個錯誤說:

在類型的方法submit(Callable<capture#1-of ?>) CompletionService<capture#1-of ?>不適用於參數 ( Callable<capture#2-of ?>

後來我只想給f.get()來處理提交的任務中拋出的異常。

那麼處理這個問題的正確方法是什麼?

回答

4

通配符在這裏不合適。 (另請注意,如果你有兩個通配符不匹配這樣,就像如果有一個名爲TU通用參數。)

的標準方法是使用<Void>

+0

'Void'好。它實際上可以確保在編譯時你的方法確實返回null(而沒有其他)。 – Thilo

+0

是的,這正是我所尋找的。從未聽說過。 – bennihepp

0

試試這個

CompletionService<Object> ecs = ...; 
    Callable<Object> c = ...; 
    Future<?> f = ecs.submit(c); 
0

的這裏的問題是,?不是標識符。它的意思是「未知的東西」。第一個「未知事物」與第二個不同。換句話說,你認爲你想提交Callable<C>CompletionService<S>。顯然它不能工作。

解決這個要麼使用Object作爲通用型的方式:

CompletionService<?> ecs = ... 
Callable<?> = ... 
Future<?> f = ecs.submit(c); 

,或者可能會更好,定義在方法層面自己的類型T並在代碼中使用它:

<T> void foo() { 
    CompletionService<T> ecs = ... 
    Callable<T> = ... 
    Future<?> f = ecs.submit(c); 
} 

您可能會在CompletionService<T> ecs = ...行中發出警告,但您可以將其禁用(僅限於此)。其餘的代碼應該沒問題。

但是這個建議聽起來不太好,泛型已被添加到Java編程語言中,以解決未知類型的問題。因此,更好的方法是在整個代碼中正確使用泛型。

0

您需要一個類型變量來聲明所有對象的類型參數匹配,即使您對類型本身不感興趣。爲了聲明一個類型變量,你必須把代碼放入一個可以聲明它的方法或構造函數中,例如

static <T> Future<T> doIt(Callable<T> c, Executor e) { 
    CompletionService<T> ecs = new ExecutorCompletionService<T>(e); 
    return ecs.submit(c); 
} 

現在,你甚至可以使用通配符稱之爲:

Callable<?> c; 
Executor e; 
Future<?> f=doIt(c, e);