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

Bri*_*idy 5 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) {
      ...
   }
   ...
}
Run Code Online (Sandbox Code Playgroud)

Fragment2:

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

   public void add(T value, Node node) {
      ...
   }
   ...
}
Run Code Online (Sandbox Code Playgroud)

片段1指定明确的是,参数必须是任一类型Ť或类型的子类型Ť.

Fragment2指定参数必须是T类型.但是从我的小知识和经验来看,我认为我也可以在这里提供T的子类型.与fragment1相同.

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

<   public <E extends T> void add(E);
---
>   public void add(T);
Run Code Online (Sandbox Code Playgroud)

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

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

感谢您的评论.

Pau*_*ora 4

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

BinaryTree<Number> numTree = new BinaryTree<>();
Integer i = 1;
numTree.add(i);
Run Code Online (Sandbox Code Playgroud)

对于片段 1,E可能会计算为Integer,但在这种情况下这是多余的。Integer 是 a Number,您也可以指定Numberfor E

numTree.<Number>add(i);
Run Code Online (Sandbox Code Playgroud)

因此,第二个片段与第一个片段没有什么不同,并且不会因未声明不必要的类型参数而造成混乱。


在某些情况下,附加类型参数会很有用。想象一下,由于某种原因您想要返回传入的值:

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

public <E extends T> E add(E value, Node node) {
   ...
   return value;
}
Run Code Online (Sandbox Code Playgroud)

现在这对调用者很有用:

Integer i2 = numTree.add(i);
Run Code Online (Sandbox Code Playgroud)

对于第二个片段,这是不可能的,即使您传入了 ,也numTree.add只能返回 a 。NumberInteger