0
 /**
   * Returns a reversed view of the specified list. For example, {@code
   * Lists.reverse(Arrays.asList(1, 2, 3))} returns a list containing {@code 3,
   * 2, 1}. The returned list is backed by this list, so changes in the returned
   * list are reflected in this list, and vice-versa. The returned list supports
   * all of the optional list operations supported by this list.
   *
   * <p>The returned list is random-access if the specified list is random
   * access.
   *
   * @since Guava release 07
   */

  public static <T> List<T> reverse(List<T> list) {
    if (list instanceof ReverseList) {
      return ((ReverseList<T>) list).getForwardList();
    } else if (list instanceof RandomAccess) {
      return new RandomAccessReverseList<T>(list);
    } else {
      return new ReverseList<T>(list);
    }

私は前にこの構文を見たことがありません:

 public static <T> List<T> reverse(List<T> list)

とは<T> List<T>どういう意味ですか? 私はそれが次のようになると思いました:

 public static List<T> reverse(List<T> list)
4

3 に答える 3

8

1 つ目<T>は、それがジェネリック メソッドであり、型変数Tとして導入されていることを示しています。それ自体がジェネリック型ではないこと忘れないでください。Lists

public static List<T> reverse(List<T> list)

...何Tを参照すると思いますか?

詳細については、ジェネリック メソッドの Java Generics FAQ エントリを参照してください。

于 2013-06-29T21:32:51.430 に答える
3

あなたの想定されるコード:

public static List<T> reverse(List<T> list)

コンパイルさえしません。

なんで?ジェネリック型であるTエンティティがコンパイラに認識されないためです。T

メソッドのコンテキストにいるとき、ジェネリック型を宣言する場合、それはどこかから取得する必要があります。あなたが提案する宣言では、囲んでいるクラスがそれを宣言しない限りT、コンパイラーがそれを関連付けることはできません。

また、ユーティリティ関数のみを持つ静的クラスのコンテキストにいる場合、このクラスは確かにジェネリックではありません。したがって、「ねえ、このメソッドにはジェネリック型が必要で、Tここで呼び出される」とコンパイラに伝える必要があります。しかし、それは呼び出すことができますMEH:

public static <MEH> List<MEH> reverse(List<MEH> list)

本質的に、ルールは次のとおりです。

  • これがジェネリック クラス自体のインスタンスにリンクされたメソッドである場合、ジェネリック型を再宣言することなく、クラスのジェネリック型宣言をメソッドで自由に再利用できます (これが、たとえば、.iterator()a のメソッドCollectionがジェネリック型を再宣言します:Collection既に宣言されています);
  • 一方、このメソッドを特定のクラスのインスタンスにリンクできない場合 (一般に静的メソッドの場合)、このメソッドの戻り値の型および/または引数を考慮する必要があります。

あなたはグアバについて話しているので、グアバ自体から別の例を挙げましょう: Closer. 以下を呼び出してインスタンスを作成します。

final Closer closer = Closer.create();

次に、このメソッドには.register()、「実装する任意の型」を引数として取るメソッドがありますCloseable。このメソッドのプロトタイプは次のとおりです。

public <C extends Closeable> C register(C closeable)

Closerクラス自体がジェネリックではないことに気付くでしょう。ただし、その.register()メソッドにはジェネリックにバインドされた引数があります。Cその宣言の利点により、 が (この場合)/extend を実装する必要がありますCloseable

このメソッドの引数と戻り値の型はどちらもたまたま thatであるため、たとえば aをそのままC送信できます。FileInputStream

final FileInputStream in; // implements Closeable

try {
    in = closer.register(new FileInputStream("meh"));
    // etc
于 2013-06-29T22:10:21.147 に答える
1

@JonSkeet がコンパイラのセマンティクスを説明したので、とにかく、ここにフリー テキストの説明を追加します。

この構文を使用するのは、返さList<T>れる の要素をメソッド引数の要素と強制的に同じ型にする場合List<T> list (または、さらに言えば、返される型とメソッドの 1 つ以上の要素との間に相関関係を強制する場合) です。引数の型) .

于 2013-06-29T21:48:40.473 に答える