从类型化中使用的泛型类型访问类型参数

时间:2011-11-18 16:17:47

标签: java generics

我发现了泛型的以下问题。考虑通用接口

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);
}

它有效。为什么?这是编译错误吗?对此的任何评论都将非常感激。

注意:

  • 我之所以不简单地将方法foo声明为void foo(A),是因为我实际上使用的是上层类型绑定的部分(&amp;)。
  • 我之所以没有将X声明为foo()中的类型变量,是因为我实际上在类级别存在问题,并且不希望不必要地增加此类的类型参数的数量

2 个答案:

答案 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)。