Java 递归泛型用法

Java 递归泛型用法,java,generics,Java,Generics,编辑:“我从‘埃里克森’那里得到了一个非常中肯的答案,但有一个附带问题(上选角?)没有在我的原始示例中明确说明,也没有用他的答案解决。我扩展了示例以涵盖其他问题,并将其包含在本文末尾。感谢您的帮助 我目前正面临一个与Java泛型相关的问题,这个问题被称为。在阅读了Jon Skeet对这个问题的回答后,我认为我已经找到了解决方案。然而,当我尝试在代码中应用它时,我发现自己遇到了不同的问题 我举了一个“小”的例子来说明我面临的问题。我希望它能足够清楚地说明我的问题 示例说明:我想构建一个节点类型可以

编辑:“我从‘埃里克森’那里得到了一个非常中肯的答案,但有一个附带问题(上选角?)没有在我的原始示例中明确说明,也没有用他的答案解决。我扩展了示例以涵盖其他问题,并将其包含在本文末尾。感谢您的帮助

我目前正面临一个与Java泛型相关的问题,这个问题被称为。在阅读了Jon Skeet对这个问题的回答后,我认为我已经找到了解决方案。然而,当我尝试在代码中应用它时,我发现自己遇到了不同的问题

我举了一个“小”的例子来说明我面临的问题。我希望它能足够清楚地说明我的问题

示例说明:我想构建一个节点类型可以变化的图。我定义了一个抽象类节点,它定义了一些基本方法,以及一个实现这些方法的具体类,即ConcreteNode。我还创建了一个名为City的ConcreteNode专门化

在一个给定的图中,一个重要的要求是所有元素都应该由相同的类型或子类型组成,即一个ConcreteNode图只能有ConcreteNode或Cities

以下是我的类的定义:

abstract class Node<T extends Node<T>>
class ConcreteNode<T extends ConcreteNode<T>> extends Node<T>
class City extends ConcreteNode<City>
问题的第二部分

有一个相关的问题,我没有包括在原始示例中,因为我认为解决方案也将适用

现在,我在GraphUtil中添加了以下方法:

static <T extends Node<T>> T getSomeNeighbor(T node) {
    return node.neighbors().iterator().next();
}
静态T getSomeNeighbor(T节点){
返回node.neights().iterator().next();
}
在我的主课上,我尝试了以下几点:

City someCity = GraphUtil.getSomeNeighbor(nyc); 
someCity.addNeighbor(new City("London")); // OK

ConcreteNode someCN1 = GraphUtil.getSomeNeighbor(nyc); 
someCN1.addNeighbor(new City("Paris")); // OK, but raw

ConcreteNode<?> someCN2 = GraphUtil.getSomeNeighbor(nyc); 
someCN2.addNeighbor(new City("Berlin")); // Does not compile

ConcreteNode<?> nc = new City("");
nc.addNeighbor(new City("Bern")); // Does not compile
City someCity=GraphUtil.getsomeneighbork(纽约);
someCity.addNeighbor(新城(“伦敦”);//好的
ConcreteNode someCN1=GraphUtil.getSomeNeighbor(nyc);
someCN1.addNeighbor(新城市(“巴黎”);//好的,不过是生的
ConcreteNode someCN2=GraphUtil.getsomenexture(nyc);
someCN2.addNeighbor(新城(“柏林”);//不编译
ConcreteNode nc=新城(“”);
nc.addNeighbor(新城(“伯尔尼”);//不编译
第一种情况有效,因为我知道返回的具体类型,并且它与参数中提供的类型一致

在第二和第三种情况下,我假设我不知道City类型。第二种情况可行,但我使用的是原始类型ConcreteNode

在第三种情况下,第二行出现编译错误:“TestCity.ConcreteNode类型中的addNeighbor(capture#3-of?)方法不适用于参数(TestCity.City)。”

在本例中,我使用“new City(“-”)作为参数,因为我不知道如何向上转换它们。在第四种情况下,我尝试向上转换City到ConcreteNode,但失败。当前编译器错误如下:“TestCity.ConcreteNode类型中的addNeighbor(capture#4-of?)方法不适用于参数(TestCity.City)"

问题:

  • 在不知道城市类型的情况下,如何修复案例2和3
  • 如何将城市向上投射到节点(或节点)
  • 感谢您的帮助。

    您可以创建泛型方法和泛型类型。使用这些方法,
    图形
    中的问题方法可以如下所示进行修复:

    static <T extends Node<T>> void addNewNeighbors1a(T node, T newNode)
    {
      node.addNeighbor(newNode);
      print("Add city to node", node.neighbors());
    }
    
    static <T extends Node<T>> void addNewNeighbors2(T node, T newNode)
    {
      node.addNeighbor(newNode);
      print("Add concrete node to node", node.neighbors());
    }
    
    public abstract <S extends T> void addNeighbor(S n);
    

    首先,静态方法中的通配符允许任何类型的节点添加,而编译器知道这是不允许的。假设你在做蛋白质的图形(比如,我做的),你有一个
    蛋白质扩展节点
    类和实例。你的通配符方法,如果有效的话,将允许我添加上述蛋白质

    要解决此问题,请尝试按照以下方式定义add方法:

    public <U extends T> void add(U other)
    
    公共作废添加(U其他)
    

    T由class参数定义,该方法允许添加T的任何子类,如局部参数U所定义。该子类应在一个方向上解决您的问题,尽管您仅限于向超类添加子类。

    对于第二部分,通配符也是一个问题。ConcreteNode可能是City不扩展的某种类型-例如,
    ConcreteNode
    不被
    City
    扩展-尽管您知道它是什么,编译器不知道。

    对于第1部分,我将使该方法具有意义

    static <T extends Node<T>> void addNewNeighbors(Node<? super T> node, T newNode)
    {
      node.addNeighbor(newNode);
    }
    

    static void addnewneights(NodeHi,谢谢你的回答:这很清楚,解决了我的一部分问题。不过,你的回答中没有涉及到它的另一个方面。我已经更新了原始帖子的另一面。如果你能帮助我,那就太好了。非常感谢。谢谢你的回答。蛋白质图确实是另一个方面相同的应用。正如erickson提到的,添加U类型对支持未来的类型很有用。但是,我最初的问题是GraphUtil方法,这些都按照他的建议解决了。现在我在原来的帖子中添加了问题的另一部分。你是对的……这意味着我的图表可以由不同的k组成混凝土节点索引,不是吗?如果我知道不是这样的话,那么我唯一的选择就是使用原始类型,或者使用铸造?我不会说这是唯一的选择,但你当前的设计让你有点受限制,是的。对不起,你更新的问题中的示例太过做作,无法帮助我想象你会有真正的问题。在你所有的示例中是的,您知道
    addNeighbor
    的参数类型(它总是
    City
    )。你能展示你真正想要写的方法吗?也就是说,参数的类型不是静态声明的方法吗?你可能还需要展示如何调用这个方法。第二部分没有用,因为我需要知道City才能写ConcreteNode
    public abstract <S extends T> void addNeighbor(S n);
    
    public <U extends T> void add(U other)
    
    static <T extends Node<T>> void addNewNeighbors(Node<? super T> node, T newNode)
    {
      node.addNeighbor(newNode);
    }
    
    ConcreteNode<? super City> nc = new City("");
    nc.addNeighbor(new City("Bern"));