簡體   English   中英

Java泛型:匹配參數的類型

[英]Java generics: matching the type of a parameter

我將如何修改它,使生成的Collection(newNodes)與傳入的Collection(節點)具有相同的類型?

public void setNodes(Collection<NodeInfo> nodes) {
    Collection<NodeInfo> newNodes = new TreeSet<NodeInfo>();
    for (NodeInfo ni: nodes) {
        newNodes.add(ni.clone());
    }
}

我懷疑那是...

public void setNodes(<T extends Collection<NodeInfo>> nodes) {
    Collection<NodeInfo> newNodes = new T<NodeInfo>()

這可能嗎?

關閉,但沒有雪茄。 如果我了解您想做什么,您的方法應如下所示:

public <T extends NodeInfo> void setNodes(Collection<T> nodes) {
    Collection<T> newNodes = new TreeSet<T>();
    for(T t : nodes) {
        newNodes.add(t);
    }
}

不幸的是,用Java編寫它是不可能的。 如果需要此效果,則有幾種選擇:

如果您要針對特定​​種類的集合進行優化,則可以使用instanceof check來檢測它。 (例如,Guava庫經常這樣做以檢測不可變的集合並進行特殊處理。)

如果您確實只需要填充一個集合,則可以要求呼叫者為您提供一個集合。

public <C extends Collection<NodeInfo>> void setNodes(C nodes, C newNodes) {
  for (NodeInfo ni : nodes) {
    newNodes.add(ni);
  }
}

如果需要根據需要進行任意數量的這些集合的功能,則可以定義一個工廠接口並使調用者提供它的一個實例:

interface Factory<C extends Collection<NodeInfo>> {
  C newCollection();
}

public <C extends Collection<NodeInfo>> void setNodes(C nodes, Factory<C> factory) {
  C newNodes = factory.newCollection();
  for (NodeInfo ni : nodes) {
    newNodes.add(ni);
  }
}

不幸的是,您無法在Java中進行new T :由於泛型是通過類型擦除在Java中實現的,所以由類型參數提供的類型信息只是靜態可用的信息,即在運行時不再可用。 因此,Java不允許對象的通用創建(請參閱Angelika Lange的Generics FAQ )。

或者,您可以使用:

  • 類型標記,即使用Class<T>對象作為參數使類型在運行時可用
  • 如果能夠在其他地方創建合適的Collection,請使用簽名void setNodes(Collection<NodeInfo> nodes, Collection<NodeInfo> newNodes)
  • 如果合適,使用標准的Collection實現,例如ArrayList<NodeInfo>
  • 深度克隆nodes ,例如使用克隆庫

    Cloner cloner = new Cloner();

    @SuppressWarnings(“ unchecked”) Collection<NodeInfo> newNodes = cloner.deepClone(nodes);

注意,JDK中的許多Collection實現本身都實現了Cloneable 一種“盡力而為”的方法可能是這樣的:

public Collection<NodeInfo> setNodes(Collection<NodeInfo> nodes) throws CloneNotSupportedException {
    Collection<NodeInfo) newNodes;

    if (nodes instanceof Cloneable) 
        newNodes = (Collection<NodeInfo>) newNodes.clone();
    else
        // Fallback in case we have a non-cloneable collection
        newNodes = new TreeSet<NodeInfo>();

    newNodes.clear();
    for (NodeInfo ni: nodes) {
        newNodes.add(ni.clone());
    }
    return newNodes;
}

對於許多輸入,這將返回相同的集合,但是如果它不能做得更好,則會退回到默認情況下返回TreeSet

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM