我发现了泛型的以下问题。考虑通用接口
public interface A<X> {
X get();
void doStuff(X x);
}
现在,让我们假设以下方法定义:
public <T extends A<?>> void foo(T t) {
bar(t);
}
由于通配符,get()的返回类型的类型信息不足。因此,我必须委托另一种&#34;绑定&#34;这个通配符是一个新的类型变量:
private <X> void bar(A<X> t) {
X x = t.get();
t.doStuff(x);
}
不允许在foo中调用bar(),编译器输出以下错误消息:
类型测试中的方法栏(A)不适用于参数(T)
但是,如果我将方法foo()更改为
public <T extends A<?>> void foo(T t) {
A<?> u = t; // No explicit cast required, no "unchecked" warning!
bar(u);
}
它有效。为什么?这是编译错误吗?对此的任何评论都将非常感激。
注意:
答案 0 :(得分:2)
我检查了代码:
public class Test
{
public interface A<X> {
X get();
void doStuff(X x);
}
public <T extends A<?>> void foo(T t) {
bar(t);
}
private <X> void bar(A<X> t) {
X x = t.get();
t.doStuff(x);
}
}
它有效。 javac 1.6.0_22。你在哪里有错误?或者我使用其他代码?
答案 1 :(得分:1)
代码:
public class Test
{
public interface A<X> {
X get();
void doStuff(X x);
}
public <T extends A<?>> void foo(T t) {
bar(t);
}
private <X> void bar(A<X> t) {
X x = t.get();
t.doStuff(x);
}
}
仅编译Java 1.6的选定版本。这个bug被记录为日食,但被Srikanth Sankaran的以下解释拒绝了:
我相信eclipse编译器行为是正确的并且匹配 JDK5和JDK7(最新)。看来JDK6的行为是一个 已经修复的回归。
基本上,这是对此处发生的事情的简要说明:
给定通用方法栏和bar(t)给出的调用站点, 推理算法没有约束来推断类型 变量X的类型。所以在考虑了参数和 预期的返回类型等,X仍未解决且符合规范 被解决为公布的下界 - 即推断为X. 对象和方法变为空白条(A)t);既然实际 参数无法转换为形式参数,推断出来 方法必须被拒绝,让我们没有适用的候选人。 因此必须拒绝来电。
呼叫栏的原因((A)t);成功就是在这种情况下X 被推断为&#34;捕获#1-of?&#34;和通用方法 使用此替换参数化将变为参数兼容性所在的void bar(A)。