Java泛型:匹配参数的类型

时间:2012-03-03 16:40:29

标签: java generics types parameters

我如何修改它,以便生成的Collection(newNodes)与传入的(节点)类型相同?

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>()

这可能吗?

4 个答案:

答案 0 :(得分:2)

关闭,但没有雪茄。如果我理解你想要做什么,你的方法应该如下:

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

答案 1 :(得分:2)

不幸的是,你用Java编写它是不可能的。如果你需要这个效果,你有几个选择:

如果您尝试针对特定类型的集合进行优化,则可以使用instanceof检查来检测它。 (例如,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);
  }
}

答案 2 :(得分:1)

不幸的是,您无法在Java中执行new T:由于泛型是通过类型擦除在Java中实现的,因此类型参数提供的类型信息仅是静态可用信息,即在运行时不再可用。因此,Java不允许通用的对象创建(参见Angelika Lange's Generics FAQ)。

或者,您可以使用:

  • 类型标记,即使用Class<T>对象作为参数,使类型在运行时可用
  • 如果您能够在其他地方创建合适的集合
  • ,请使用签名void setNodes(Collection<NodeInfo> nodes, Collection<NodeInfo> newNodes)
  • 如果合适的话,使用标准的Collection实现,例如: ArrayList<NodeInfo>
  • 深度克隆nodes,例如使用The Cloning Library

    Cloner cloner = new Cloner();

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

答案 3 :(得分:0)

请注意,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