泛型类类型中的参数化方法

时间:2012-08-26 14:31:02

标签: java generics parameterized

我有一个相当简单的问题。我找不到答案。

这两个代码片段有区别吗?有什么区别?

片段1:

public class BinaryTree<T extends Comparable<? super T>> {
   ...
   public <E extends T> void add(E value) {
      ...
   }

   public <E extends T> void add(E value, Node node) {
      ...
   }
   ...
}

Fragment2:

public class BinaryTree<T extends Comparable<? super T>> {
   ...
   public void add(T value) {
      ...
   }

   public void add(T value, Node node) {
      ...
   }
   ...
}

Fragment1明确指定参数 value 必须是 T 类型或 T 类型的子类型。

Fragment2指定参数 value 必须是 T 类型。但是根据我的小知识和经验,我认为我还可以在这里提供 T 的子类型。和fragment1一样。

我查看了这两个片段的反汇编字节码。确实存在差异:

<   public <E extends T> void add(E);
---
>   public void add(T);

这只反映了源代码......

我只是没有意义。而且我也找不到示例应用程序,它显示了差异。

感谢您的评论。

2 个答案:

答案 0 :(得分:4)

在这种情况下没有区别。我们以BinaryTree<Number>为例,尝试添加Integer

BinaryTree<Number> numTree = new BinaryTree<>();
Integer i = 1;
numTree.add(i);

对于片段1,E可以评估为Integer,但在这种情况下这是多余的。 Integer Number,您也可以为Number指定E

numTree.<Number>add(i);

因此,第二个片段与第一个片段没有什么不同,并且不会因为没有声明不必要的类型参数而感到困惑。


在某些情况下,其他类型参数会很有用。想象一下,你想要返回传入的值:

public <E extends T> E add(E value) {
   ...
   return value;
}

public <E extends T> E add(E value, Node node) {
   ...
   return value;
}

现在这对调用者有用:

Integer i2 = numTree.add(i);

使用第二个代码段是不可能的,即使您传入了numTree.addNumber也只能返回Integer

答案 1 :(得分:1)

不,add()方法的两种变体之间没有区别。 Java的方法参数已经在接受的类型上建立了上限,这是使用类型变量extends的{​​{1}}形式完成的相同约束。

您的类型变量不会添加任何新信息,也不会添加任何其他约束。传递<E extends T> 类型的参数或任何扩展T 的类型已经合法。你的类型变量T确实提供了一种再次引用实际参数类型的方法 - 比方说,如果你想要确保第二个方法参数与第一个类型相同 - 但在你的情况下,你“我没有使用<E extends T>