如果我有一個方法,例如返回泛型方法
public INode getNode(final int offset);
我認爲它不添加東西,使該方法的返回類型通用的,比如:
public <T extends INode> T getNode(final int offset);
或者我錯過了什麼?我認爲泛型返回類型只有在其中一個參數是相同類型(或超級/子類型)時纔有價值?
如果我有一個方法,例如返回泛型方法
public INode getNode(final int offset);
我認爲它不添加東西,使該方法的返回類型通用的,比如:
public <T extends INode> T getNode(final int offset);
或者我錯過了什麼?我認爲泛型返回類型只有在其中一個參數是相同類型(或超級/子類型)時纔有價值?
public <T extends INode> T getNode(final int offset);
這不僅不提供任何額外的信息給調用者,而是徹頭徹尾的危險:實現一個方法簽名的唯一方法是使用選中投,不能是類型安全,因爲一個方法的類型參數是由其調用者指定的(顯式地或暗示地通過類型推斷),並且類型參數對於此方法的實現不可用。例如,考慮下面的程序:
class NodeCollection {
private INode[] nodes = new INode[42];
public <T extends INode> T getNode(final int offset) {
return (T) nodes[offset];
}
public <T extends INode> setNode(final int offset, T node) {
nodes[offset] = node;
}
}
class ANode implements INode {}
class BNode implements INode {
void foo();
}
public class Test {
public static void main(String[] args) {
NodeCollection nc = new NodeCollection();
nc.setNode(0,new ANode());
BNode b = nc.getNode(0); // throws ClassCastException (sic!)
}
}
最佳實踐:不要使用未經檢查的演員,除非你是真的在運行肯定這將是類型正確的。
我認爲泛型返回類型只有在其中一個參數是相同類型(或超/子類型)時纔有效?
還有更多的情況下,例如:
public <T> T getFavorite(Class<T> clazz) {
return clazz.cast(favorites.get(clazz));
}
或
interface List<E> {
E get(int index);
}
或在科林的答案,其中類型變量僅僅出現類型參數在返回的例子類型,這是由於類型擦除可接受的。
編輯:
我覺得有沒有類型保存方式,如果一個人想投的確切類型的節點(而不是的instanceof有它前面)
當然有是,它叫visitor pattern。
我們堅持節點爲INode,即每個節點都必須實現的INode接口。然後我們有一個用於「結構」節點的接口IStructNode。事務遊標提供上述方法,例如moveTo(nodeID),而它在內部調用getNode(offset)。另一種方法是getNode(),它將節點作爲INode進行傳遞,將getStructuralNode()作爲IStructNode進行傳遞,或者將其封裝在實現空對象模式的「NullNode」中。我認爲沒有類型保存方式,如果一個人想投到節點的確切類型(而不是instanceof必須先於它) – Johannes 2012-04-09 21:54:05
這是否應該修改您的問題?如果是這樣,那麼請使用問題的編輯按鈕。這也可以讓你構造和格式化修正。 – meriton 2012-04-09 22:03:04
是的,當然,訪問者模式;-)我已經在大約一年前實現了它,但是沒有想到它......好啊。 – Johannes 2012-04-10 05:42:56
在您給出的示例中,除了強制實施的開發人員轉換返回值(在T
中)之外,它並不真正添加任何值。 (除非它有辦法獲得T
的值,但爲此,它需要調用另一個返回T
的方法,因此您只需將演員組進一步移動即可。如果你正在向我們展示
有少數情況下,一般只適用於返回值可能是有用的,例如:。
public static <T> Collection<T> generateCollection() {
return new ArrayList<T>();
}
這允許你創建一個對象Collection
T
而不必做任何演員。
或者,如果你想開發人員做的實施施展他的對象(主要是工程時,上述對象使用泛型),例如,從Collections
:
public static final <T> Set<T> emptySet() {
return (Set<T>) EMPTY_SET;
}
資源:
它可能會增加更多的價值,但是,如果在類中定義泛型參數,我會認爲它會增加更多的價值。 – Joel 2012-04-09 21:05:37
是什麼問題?什麼「不加什麼東西」意味着什麼? – 2012-04-09 21:57:26