11

Tパラメータを使用するジェネリックなメソッドは確かに便利です。ただし、メソッドに などの引数を渡すと、ジェネリック メソッドの使用がどうなるか興味がありますClass<T> clazz。使えそうなケースを思いつきました。おそらく、クラスのタイプに基づいてメソッドの一部のみを実行したいでしょう。例えば:

/** load(File, Collection<T>, Class<T>)
* Creates an object T from an xml.  It also prints the contents of the collection if T is a House object.
* @return T
* Throws Exception
*/
private static <T> T void load(File xml, Collection<T> t, Class<T> clazz) throws Exception{
    T type = (T) Jaxb.unmarshalFile(xml.getAbsolutePath(), clazz);  // This method accepts a class argument.  Is there an alternative to passing the class here without "clazz"?  How can I put "T" in replace of "clazz" here?
    if (clazz == House.class) {
         System.out.println(t.toString());
    } else {
         t.clear();
    }
    return T;
}

これは受け入れられた慣行ですか?Class<T> clazzジェネリック メソッドで引数が役立つのはいつですか?

4

7 に答える 7

11

これは受け入れられた慣行ですか?

まあ、私には..いや、そうではありません。の型にいくつかの境界を単純に定義できる場合、私にはやや無意味に思えますT。例えば:

private static <T extends House> void load(Collection<T> t)

これにより、オブジェクトが のタイプまたはサブクラスのいずれかであることが保証されますが、タイプまたはそのサブクラスのインスタンスのみが必要な場合は、実際には次のようにする必要があります。HouseHouseHouse

private static void load(Collection<House> houses)

ジェネリックの考え方は、メソッドまたはクラスをより順応性と拡張性を高めることです。そのため、ジェネリックの概念そのものがそのような詳細を抽象化することである場合、メソッド本体でクラスの型を比較し始めるのは直観に反するように思えます。

于 2013-08-22T12:54:41.820 に答える
4

ジェネリック型が他の方法で派生できない場合にのみ、クラス オブジェクトを渡します。Tあなたの場合、コンパイラはコレクションから推測できるはずです。特定のオブジェクトを異なる方法で扱うには、ポリモーフィズムを使用します。たとえば、 House#something()andOther#something()を呼び出すだけanyObject.something()です。

于 2013-08-22T12:53:05.503 に答える
4

許容できると思います、回避できる場合は回避する必要があります。通常、異なる型を受け入れる異なるメソッドを持つことができる場合は、if句を使用してパラメーターの型に応じて異なることを行う 1 つのメソッドの代わりにそれを行います。特定のタイプに固有にしたい操作をクラスに委譲することもできます。

あなたの場合、 を使用してコレクションの各要素の型を簡単にテストしてinstanceof、特定の型に必要なことを行うことができます。ただし、リストが空の場合は機能しません。

典型的な用途は、タイプを作成するためにタイプを取得する必要があり、別の方法でタイプを見つけることができる場合です。たとえば、Spring はそれを使用して、名前から Bean をロードします

<T> T getBean(Class<T> requiredType)

その場合、(キャストせずに)回避することはできません。

于 2013-08-22T12:57:12.173 に答える
3

Class<T>ジェネリックの前に引数を渡す場合にのみ、ジェネリックで引数を渡しますClass。つまり、Classオブジェクトが何らかの方法で使用されている場合のみです。Generics は、コンパイル時の型チェック ツールとして機能します。ただし、どの引数を渡すかは、プログラムのランタイム ロジックによって決定される必要があり、ジェネリックとは無関係である必要があります。

于 2013-08-23T10:42:37.367 に答える
2

Classジェネリックの一般的な使用例として、オブジェクトの実行時の型をチェックするためにオブジェクトを渡すことは見たことがありません。それを行っている場合、クラス構造をセットアップするためのより良い方法がある可能性が高くなります。

見たのは、問題のクラスの新しいインスタンスを作成する必要があるか、そうでなければリフレクションを使用する必要があるかどうかです。Classその場合、Java は型消去のおかげで実行時にオブジェクトを派生させることができないため、オブジェクトを渡す必要があります。

于 2013-08-22T13:02:48.260 に答える
1

あなたの場合、実際に Generic パラメータを持つことは厳密には必要ありません。説明している関数の出力は入力のタイプに依存しないため、ワイルドカードを使用することもできます。

private static void stuff(Collection<?> t){
    Object next = t.iterator().next(); //this is ugly and inefficient though
    if(next instanceof House){  
        System.out.print(next.toString());
    }else{
        t.clear();
    }
}

ジェネリック パラメーターを使用する必要があるのは、関数の結果の型がパラメーターの型に依存する場合のみです。

コードで必要な場合は、型に対応する Class を渡す必要があります。ほとんどの場合、これは次の場合に発生します。 - T にキャスト/型チェック オブジェクトが必要な場合 - シリアライゼーション/デシリアライゼーションが関係している場合。- 関数内の T のインスタンスにアクセスできず、必要なときに getClass() メソッドを呼び出すことができません。

すべてのジェネリック関数にクラスを渡すと、ほとんどの場合、不要なパラメーターを渡すことになり、これは悪い習慣と見なされます。

私は過去に同様の議論に答えました: いつジェネリックメソッドを使用し、いつワイルドカードを使用しますか?

于 2013-08-22T13:13:45.927 に答える