当类型是通配符时,如何将通用结果用作通用参数?

时间:2010-01-28 22:14:22

标签: java generics wildcard

[更新]实际情况比我最初提出的问题要复杂一些。我已经改变了一些代码来反映这一点。[/ UPDATE]

我对以下行为感到有点难过。给出如下代码:

interface Inter<T> {
  T makeT();
  void useT(T t);
}

public class Foo {
  public void bar(Qux q) {
    Inter<?> x = getInterForQux(q);
    x.useT(x.makeT());
  }

  Inter<?> getInterForQux(Qux q) {
    if( someTest(q) ) {
      return (Inter<Integer>) mkAnInterInt();
    } else {
      return (Inter<Double>) mkAnInterDouble();
    }
  }
}

Javac给了我错误:

  

在&lt; capture#478 of?&gt;中使用T(捕获#478?)不能应用于(java.lang.Object)

而Eclipse给了我:

  

在Inter&lt; capture#1-of?&gt;类型中使用T(捕获#1-of?)的方法。是   不适用于论点   (捕获#2-of?)

显然,无论T是什么,makeT()的结果类型都与useT()的参数类型相同。为什么我不能这样做?有解决方法吗?

3 个答案:

答案 0 :(得分:4)

使用通配符时,编译器无法看到x.makeT()的返回类型和x.useT()的参数类型相同。为了保证它们是相同的,你应该在这里使用泛型方法:

public class Foo { 
    public <T> void bar(Inter<T> x) { 
        x.useT(x.makeT()); 
    } 
} 

答案 1 :(得分:1)

这是合乎逻辑的,因为Inter<?>.makeT()可以返回任何内容,而Inter<?>.useT(..)会消耗任何内容,但两个 anythings 可能会有所不同。

那会解决它:

public <T> void bar(Inter<T> x) {
    x.useT(x.makeT());
}

答案 2 :(得分:0)

使用捕获助手:

public void bar(Qux q) {
    Inter<?> x = getInterForQux(q);
    barPrivate(x);
}
private <T> void barPrivate(Inter<T> x) {
    x.useT(x.makeT());
}

这为您提供了bar的相同签名