有他們暴露不同的接口和方法合同有界通配符和類型參數有什麼區別?
<N extends Number> Collection<N> getThatCollection(Class<N> type)
和
Collection<? extends Number> getThatCollection(Class<? extends Number>)
有他們暴露不同的接口和方法合同有界通配符和類型參數有什麼區別?
<N extends Number> Collection<N> getThatCollection(Class<N> type)
和
Collection<? extends Number> getThatCollection(Class<? extends Number>)
之間的差異。
第一個聲明應返回其元素類型與參數類相同的集合。編譯器推斷N
的類型(如果未指定)。所以,下面的兩個語句中使用第一次申報時是有效的:
Collection<Integer> c1 = getThatCollection(Integer.class);
Collection<Double> c2 = getThatCollection(Double.class);
第二個聲明不聲明返回的集合類型參數的參數類之間的關係。編譯器假定他們是不相關的,所以客戶端必須使用返回類型爲Collection<? extends Number>
,不管理由是什麼:
// Invalid statements
Collection<Integer> c1 = getThatCollection(Integer.class); // invalid
Collection<Double> c2 = getThatCollection(Double.class); // invalid
Collection<Number> cN = getThatCollection(Number.class); // invalid
// Valid statements
Collection<? extends Number> c3 = getThatCollection(Integer.class); // valid
Collection<? extends Number> c4 = getThatCollection(Double.class); // valid
Collection<? extends Number> cNC = getThatCollection(Number.class); // valid
建議
如果確實存在之間的關係在返回的類型參數和傳遞的參數之間鍵入,使用第一個聲明要好得多。如上所述,客戶端代碼更清潔。
如果關係不存在,那麼最好避免第二個聲明。使用有界通配符的返回類型會強制客戶端在任何地方使用通配符,因此客戶端代碼會變得分崩離析且無法讀取。約書亞布洛赫emiffisize,你應該Avoid Bounded Wildcards in Return Types(幻燈片23)。儘管返回類型中有界的通配符可能有用,但在某些情況下,結果代碼的醜陋性應該恕我直言,恕不另行通知。
在這種特殊情況下,沒有。然而第二個選項更靈活,因爲它允許您返回包含不同類型元素(即使它也是Number)的集合,而不是包含collection參數的類型。
具體的例子:
Collection<? extends Number> getRoot(Class<? extends Number> number){
ArrayList<Integer> result=new ArrayList<Integer>();
result.add(java.util.Math.round(number);
return result)
}
1爲的差異明確的解釋。小小的狡辯 - 我認爲你假設第一個總是更好的選擇 - 我會說「不用說」更好的選擇取決於上下文。 – 2009-11-17 17:23:11
@Steve謝謝!我補充說明了爲什麼要避免第二種說法。 – notnoop 2009-11-17 17:30:40
+1非常棒的答案! – Stephan 2013-05-22 10:38:22