我正在尝试使用一个类型参数class MyClass<E>
创建一个泛型类,它具有第二个泛型类的类变量,该类具有两个类型参数SecondClass<V, E>
。因为对于我的代码而言,V
的类型无关紧要,我将该变量的类型声明为SecondClass<?, E> var
。在MyClass实现的某个时刻,我在var上调用一个返回V,public V foo(E e)
的方法,然后将这个V类型的对象传递给var的另一个方法public int bar(V v)
。但是,由于我只是模糊地理解的原因,这不能编译,但我相信它在here中得到解释。
显然,抓住了? foo返回的不同于捕获的?酒吧需要。但为什么?无论V的实际类型是什么,它们必须对于两种方法都是相同的,因为它们是在同一实例上调用的。我在这里缺少什么?
最终,我想知道的是:为了使代码编译,我需要更改什么,而不将V添加到MyClass的类型参数? (我不想强制MyClass的用户指定V的类型,因为它应该无关紧要)
为了给你一个更具体的例子,这里是我正在研究的简化版本。正如您可能已经通过类型参数猜测的那样,它涉及图形。 MyClass
转换为EdgePainter
,SecondClass
转换为Graph
。使用此代码,编译错误位于EdgePainter.getColor(E)
的第一行。
class Graph<V, E>
{
public V getTarget(E edge)
{
return null;
}
public int getInDegree(V vertex)
{
return 0;
}
}
class EdgePainter<E>
{
private static final Color COLOR_FOR_MANY_EDGES = Color.RED;
private static final Color COLOR_FOR_FEW_EDGES = Color.BLUE;
private Graph<?, E> graph;
public EdgePainter(Graph<?, E> aGraph)
{
graph = aGraph;
}
public Color getColor(E edge)
{
// My compiler says:
// The method getInDegree(capture#3-of ?) in the type
// Graph<capture#3-of ?,E> is not applicable for the arguments
// (capture#4-of ?)
int degree = graph.getInDegree(graph.getTarget(edge));
if (degree > 10)
return COLOR_FOR_MANY_EDGES;
else
return COLOR_FOR_FEW_EDGES;
}
}
答案 0 :(得分:3)
您可以通过调用泛型方法捕获通配符。
public Color getColor(E edge) {
return getColorInternal(graph, edge);
}
private <X> Color getColorInternal(Graph<X, E> g, E e) {
int degree = g.getInDegree(g.getTarget(e));
// ...
}
这是一个典型的场景。您需要实现的类型参数,但希望将其隐藏在API用户中。如果许多方法受到影响,定义一个单独的,可能是嵌套的类EdgePainterInternal
会很有帮助。此内部实现具有第二个类型参数G
,公开可见的实现EdgePainter
委托所有调用EdgePainterInternal
的实例。