JDK是正确的。第二种方法没有比第一种更具体。从JLS3#15.12.2.5

“非正式的直觉是,如果第一种方法处理的任何调用都可以传递给另一个方法而没有编译时类型错误,则一个方法比另一个方法更具体。”

这里显然不是这种情况。我强调了任何调用。一种方法比另一种方法更具体的属性纯粹取决于两种方法本身。每次调用都不会改变。

正式分析您的问题:m2比m1更具体吗?

m1: void setValue(Parameter parameter, R value)

m2: void setValue(Parameter parameter, Field value)

首先,编译器需要根据初始约束来推断R:

Parameter   <

Field       <

根据R=V15.12.2.7中的推理规则,结果为

现在我们替换R并检查子类型关系

Parameter   <:>

Field       <:>

根据4.10.2中的子键入规则,第二行不成立。因此,m2比m1更具体。

V不在Object此分析中;分析考虑了的所有可能值V。

我建议使用不同的方法名称。绝对不需要过载。

这似乎是Eclipse中的重要错误。规范非常清楚地表明在此步骤中未替换类型变量。Eclipse显然首先进行类型变量替换,然后检查方法特异性关系。

如果在某些示例中这种行为更“明智”,则在其他示例中则不是。说,

m1: void check(List list, T obj) { print("1"); }

m2: void check(List list, T num) { print("2"); }

void test()

check( new ArrayList(), new Integer(0) );

m2比m1更“直观”且正式地符合规格,并且测试打印“ 2”。但是,如果先进行替换T=Integer,则这两种方法将完全相同!

对于更新2

m1: void setValue(Parameter parameter, R value)

m2: void setValue(Parameter parameter, Field value)

m3: void setValue2(Parameter parameter, Field value)

s4:             setValue(parameter, value)

这里,m1不适用于方法调用s4,因此m2是唯一选择。

根据15.12.2.2,要查看m1是否适用于s4,首先,进行类型推断,得出的结论是R = T; 然后我们检查Ai :< Si,导致Field <: t>

这与先前的分析是一致的-如果m1适用于s4,则m2处理的任何调用(本质上与s4相同)都可以由m1处理,这意味着m2比m1更具体,这是错误的。

以参数化类型

考虑以下代码

class PF

{

public void setValue(Parameter parameter, T value) {

}

public void setValue(Parameter parameter, Field value) {

}

}

void test()

PF pf2 = null;

Parameter p2 = getP2();

Field f2 = getF2();

pf2.setValue(p2,f2);

编译没有问题。根据4.5.2,其中的方法类型为带替换的PF方法。也就是说,方法是PFT=Objectpf2

public void setValue(Parameter parameter, Object value)

public void setValue(Parameter parameter, Field value)

第二种方法比第一种更具体。