5

かなり簡単な質問があります。でも検索しても答えが見つかりません。

これらの2つのコードフラグメントに違いはありますか?そして、違いは何ですか?

フラグメント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) {
      ...
   }
   ...
}

フラグメント2:

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

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

Fragment1は、パラメーター値がタイプTまたはタイプTのサブタイプのいずれかでなければならないことを明示的に指定します。

Fragment2は、パラメーターがタイプTでなければならないことを指定しています。しかし、私の知識と経験から、ここでTのサブタイプを提供することもできると思います。フラグメント1と同じです。

これら2つのフラグメントの分解されたバイトコードを調べました。確かに違いがあります:

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

それはソースコードを反映しているだけです...

意味がわからない。また、違いを示すサンプルアプリケーションも見つかりません。

コメントありがとうございます。

4

2 に答える 2

4

この場合、違いはありません。例として、 :BinaryTree<Number>を追加してみましょう。Integer

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

フラグメント1では、とE評価される可能性がありIntegerますが、この場合は不要です。Integer は、 であり、次のように指定するNumberこともできます。NumberE

numTree.<Number>add(i);

このため、2番目のスニペットは最初のスニペットと同じであり、不要な型パラメーターを宣言しないことで混乱が少なくなります。


追加のタイプパラメータが役立つ場合があります。何らかの理由で、渡された値を返したいと想像してみてください。

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.addのみを返すことができる2番目のスニペットを使用します。NumberInteger

于 2012-08-26T14:53:08.977 に答える
1

いいえ、この方法の2つのバリエーションに違いはありませんadd()。Javaのメソッド引数は、受け入れられる型の上限extendsをすでに確立しています。これは、型変数の形式を使用して達成されるのと同じ制約です<E extends T>

型変数は新しい情報を追加せず、追加の制約も追加しません。T 型またはを拡張する任意の型Tの引数を渡すことはすでに合法でした。型変数<E extends T>は、実際の引数の型を再度参照する方法を提供します。たとえば、最初の型と同じ型であることを確認したい2番目のメソッドパラメーターがある場合は、使用していません。のE

于 2012-08-26T14:56:20.720 に答える