3

ここで G.myUglyList リストの内容を取得し、それを Outer.send() メソッドに渡したいと思います。これがコンパイラエラーを引き起こす理由がわかりません。? extends Inner は Outer をパラメータ化するタイプです。では、渡されたインナーを拒否するのはなぜですか? タイプではない「? extends Inner」が必要です。

List<Outer<? extends Inner>>Inner のサブタイプを取得できるように、リストを as として宣言する必要があります。(これがなぜなのかについては、以下の編集を参照してください)

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>

edit : 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

outerタイプOuter<? extends Inner>、つまり の未知のサブタイプでInnerあり、そのsendメソッドは同じサブタイプのオブジェクトを取ります。

たとえばouter、タイプの場合は がOuter<OtherInner>必要outer.sendOtherInnerなるため、outer.send(xxx)間違っている可能性があります。

于 2012-10-23T04:10:54.210 に答える
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 に答える
1

PECS - 生産extends者 消費者super

outerは でパラメータ化されているため、そのメソッドには何も( を除く)extends渡すことはできません。nullsend

于 2012-10-23T18:39:34.273 に答える
1
 for (Outer<? extends Inner> outer : myUglyList) {
     outer.send(xxx); //error
 }

そのOuter<? extends Inner> outerため、実際の型は不明です ( ?)。sendは、を拡張する未知のものを取り、拡張するがまだ未知のものInnerouter持っています。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 に答える