2

次のコードを検討してください (2 つの質問はコード内にあります)。

import java.util.*;

public class Tree<T> {
    private T info;
    private List<Tree<? extends T>> children = new ArrayList<Tree<? extends T>>();

    public Tree<? extends T> getChildren(int n) {
        return children.get(n);
    }

    public void addChildren(Tree<? extends T> children) {
        this.children.add(children);
    }

    public static void main(String[] args) {
        Tree<?> b2; // so b2 is a reference of a Tree of unknown type
        b2 = new Tree<Number>(); /* to allow b2 to call addChildren() with Tree<? extends Number> aguments */
        b2.addChildren(new Tree<Number>()); // 1) why it doesn't work ?
        b2.addChildren(new Tree<Integer>()); // neither does this one!
        b2.addChildren(new Tree<>()); // 2) but with diamond <> it works ?
    }
}
  1. なぜ機能しb2.addChildren(new Tree<Number>())ないのですか?
  2. しかし、それはダイヤモンド <> で動作しb2.addChildren(new Tree<>())ます。コンパイラがダイアモンド <> 内で使用する型リストはどれですか?
4

1 に答える 1

5

b2問題は、 の型を持つと宣言したことですTree<?>

メイン メソッドを 2 つのメソッドとして書き直すと、問題はより明確になります。

public static void main(String[] args) {
    test(new Tree<Number>());
}

private static void test(Tree<?> b2) {
    // "<?>" means we don't know what the generic type of b2 is, so
    // the compiler can't possibly know if it's safe to add any type
    // of children...

    b2.addChildren(new Tree<Number>()); // 1) why it doesn't work ?
    b2.addChildren(new Tree<Integer>()); // neither does this one!
    b2.addChildren(new Tree<>()); // 2) but with diamond <> it works ?
}

作成したとしてもnew Tree<Number>()、その情報をすぐに破棄しています。あなたのコードは、 「ある種のツリーですが、どのタイプかわかりません」という意味b2であるため、不明なタイプのツリーが含まれていることを覚えているだけです。Tree<?>

Tree の型がわからないのでaddChildren(new Tree<Number>())、 、 or 、またはnew Tree<Integer>()を安全に呼び出すことができるかどうかはどうすればわかりますnew Tree<String>()new Tree<JTable>()? コンパイラにはわかりません。そこに何を入れたか覚えているかもしれb2ませんが、 の型にはその情報が含まれていないため、コンパイラには知る方法がありません。

于 2014-12-30T16:13:51.187 に答える