1

これは、パラメーター化されたメソッドに関するこの前の質問の拡張です。同じ本を読んでいます。前の質問の例の後、著者は

BinaryTree<T extends Comparable<? super T>>

次のコンストラクタを追加することにより、クラスをもう一度(そして彼は今回は実際にそうします)

public  <E extends T> BinaryTree(E[] items) {
    for(E item : items) {
        add(item);
}

前の質問の精神で、代わりにこのコンストラクターを試しました:

public BinaryTree(T[] items) {
    for(T item : items) {
        add(item);
    }
}

サンプルコードは私のコンストラクターでコンパイルされません:

public static void main(String[] args) {
    Manager[] managers = { new Manager("Jane", 1), new Manager("Joe", 3), new Manager("Freda", 3), new Manager("Bert", 2), new Manager("Ann", 2), new Manager("Dave", 2) };
    BinaryTree<Person> people = new BinaryTree<>(managers);
}

前の質問の add() メソッドの変更とこのコンストラクターの変更の違いは何ですか? コンストラクターで T のサブタイプを渡すことができないのはなぜですか?

4

1 に答える 1

2

2 番目のコンストラクターの場合、コンパイラーが

new BinaryTree<>(managers)

を推測する必要がTあり<>ます。この場合、推論は : に基づいていmanagersますT[]=Manager[] => T=Manager

したがって、式はBinaryTree<Manager>に代入できない を生成しBinaryTree<Person>ます。

2 つの回避策:

new BinaryTree<Person>(managers);

new BinaryTree((Person[])managers);

最初のコンストラクターの場合

<E extends T> BinaryTree(E[] items)

ここで推測すべきことが 2 つEありTます。new BinaryTree<>(managers)

E=Managerは推測されます。ただしT、まだ推測されていません。次に、コンパイラはターゲットの型を調べBinary<Person>、それを推測するのに役立ちますT=Person


Java の型推論は非常に厄介です。私が今説明したことをプログラマーが学ぼうとするのはなぜでしょうか? 教訓は、疑わしい場合は、型引数を明示的に指定することです。

2 つのコンストラクターのうち、私は間違いなく を選択しますBinaryTree(T[] items)。このEバージョンは、利点のない複雑さだけです (ただし、この特定の例ではよりうまく機能します)。

于 2013-02-27T02:14:07.920 に答える