3

我想在这里获取 G.myUglyList 列表的内容并将其传递给 Outer.send() 方法。我不明白为什么这会产生编译器错误。? extends Inner 是我参数化 Outer 的类型。那么为什么它拒绝传递给它的 Inner 呢?它想要一个“? extends Inner”,它不是一种类型。

我希望将列表声明为List<Outer<? extends Inner>>它可以采用 Inner 的子类型。(请参阅下面的编辑了解为什么会这样)

interface Outer<T> {
    void send(T message);
}
interface Inner {}
interface Inner2 extends Inner {}

public class G {

    List<Outer<? extends Inner>> myUglyList;

    void foo() {
        Inner xxx = null;
        for (Outer<? extends Inner> outer : myUglyList) {
            outer.send(xxx); //error
        }
    }
}

我收到此错误:

error: method send in interface Outer<T#2> cannot be applied to given types;
required: CAP#1
found: Inner<T#1>
reason: actual argument Inner<T#1> cannot be converted to CAP#1 by method invocation conversion
where T#1,T#2 are type-variables:
T#1 extends Object declared in class G
T#2 extends Object declared in interface Outer
where CAP#1 is a fresh type-variable:
CAP#1 extends Inner<T#1> from capture of ? extends Inner<T#1>

编辑:我得到了很多答案,说只是列出 type List<Outer<Inner>>,但这是不正确的。如果这样做,我将无法添加 Inner 的子类型。如果我尝试添加一个Outer<Inner2>,它会失败。所以 list 必须是 type List<Outer<? extends Inner>>

interface Inner2 extends Inner {}        
class G {
  void foo() {
    Outer<Inner2> foiled = null;
    myUglyList.add(foiled);   //this will fail if list is of type List<Outer<Inner>>
    Inner xxx = null;
    for (Outer<? extends Inner> outer : myUglyList) {
    outer.send(xxx); //error
  }
4

5 回答 5

3

更改您的代码:

interface Outer<T> {
    void send(T message);
}
interface Inner {}
interface Inner2 extends Inner {}

public class G {

    List<Outer<Inner>> myUglyList;

    void foo() {
        Inner2 xxx = null;
        for (Outer<Inner> outer : myUglyList) {
            outer.send(xxx); //error
        }
    }
}

它会编译

更新:

// No matter if you put 'T extends Inner' here, the 'add' won't compile
interface Outer<T extends Inner> {
    void send(T message);
}
interface Inner {}
interface Inner2 extends Inner {}

public class G {

    List<Outer<Inner>> myUglyList;

    void foo() {
        Outer<Inner2> foiled = null;

        // This way, the 'add' invocation will compile, but it 
        // breaks the generic and generates a warning.
        //
        // Casting 'foiled' to (Outer<Inner>) will also fail
        // because the compiler sees Outer<Inner2> as complete different type
        // from Outer<Inner>
        myUglyList.add((Outer) foiled);  

        Inner xxx = null;
        for (Outer<Inner> outer : myUglyList) {
            outer.send(xxx); //error
        }
    }
}
于 2012-10-23T04:07:49.293 回答
2

只需声明

List<Outer<Inner>> myUglyList;

然后,您可以Inner不受限制地添加 的子类型。通过声明它

List<Outer<? extends Inner>> myUglyList;

您说的myUglyList是“列表Outer<some specific (but unknown) subtype of Inner>”。那不是你想要的。

于 2012-10-23T04:08:07.823 回答
2

outer是 type Outer<? extends Inner>,即某个未知的子类型,Inner并且它的send方法接受一个相同子类型的对象。

例如outer,可能是 type Outer<OtherInner>,然后outer.send需要 a OtherInner,所以outer.send(xxx)是错误的。

于 2012-10-23T04:10:54.210 回答
1
 for (Outer<? extends Inner> outer : myUglyList) {
     outer.send(xxx); //error
 }

其中,Outer<? extends Inner> outer,所以实际类型是未知的(?)。send接受一些未知的延伸Inner,也outer有一些延伸Inner但仍然未知的东西。

更新

interface Outer<T extends Inner> {
    void send(T message); //this can take instance of subtype of Inner
}
interface Inner {}
interface Inner2 extends Inner {}

class G {

    List<Outer<Inner>> myUglyList; //you can add instances of subtypes of Inner

    void foo() {
        Inner xxx = null;
        for (Outer<Inner> outer : myUglyList) {
            outer.send(xxx); //error
        }
    }
}
于 2012-10-23T04:09:54.033 回答
1

PECS - 生产者extends消费者super

因为outer是用 参数化的extends,所以你不能将任何东西(除了null)传递给它的send方法。

于 2012-10-23T18:39:34.273 回答