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

对于第二个构造函数,当编译器看到

new BinaryTree<>(managers)

它需要推断T. <>在这种情况下,推理基于managers: T[]=Manager[] => T=Manager

因此,表达式产生 a BinaryTree<Manager>,它不能分配给BinaryTree<Person>

两种解决方法:

new BinaryTree<Person>(managers);

new BinaryTree((Person[])managers);

对于第一个构造函数

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

我们现在有两件事要推断,E并且T, 在表达式中new BinaryTree<>(managers)

现在E=Manager推断;但是T还没有推断出来。然后编译器查看目标类型Binary<Person>,这有助于推断T=Person


Java 类型推断非常混乱。为什么程序员会关心学习我刚刚描述的内容?教训是,当有疑问时,明确地提供类型参数。

在这两个构造函数之间,我肯定会选择BinaryTree(T[] items). 该E版本只是更复杂而没有好处(尽管对于这个特定示例它恰好工作得更好)

于 2013-02-27T02:14:07.920 回答