0

私は次の機能を持っています:

/**
 * Finds all entities of a certain type
 * @param <T> The type of the entity
 * @param entityType The class of the entity
 * @return A list of all the entities found, null if the entity is not in the database
 * or on error
 */
public <T> List<T> findAll(Class entityType) 
{
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    cq.select(cq.from(entityType));
    return getEntityManager().createQuery(cq).getResultList();
}

かなり反復的であることに注意してください。クラスをパラメーターとして取る必要がないように、この関数をリファクタリングできる方法はありますか。渡されたジェネリック型を使用できる方法はありますか?

4

6 に答える 6

2

いいえ、できません — 直接。いくつかの段落で、この問題を回避する別の方法を紹介します。

Java ジェネリックは型消去を介して実装されます。つまり、すべての型情報が実行時に取り除かれます。メソッドが呼び出されると、それが を返すことになっていることを認識していますListが、実行時に を返すことになっていることを伝えるものは何もありませんList<Foo>。コンストラクターは、ジョブを実行するためにクラス オブジェクトにアクセスする必要はArrayListありません。ただし、コードはそうです。

これを回避するには、クラスを渡すだけです。これは (ジェネリック クラスではなく) ジェネリック メソッドであるため、実行できます。メソッドの宣言を次のように変更すると、

public <T> List<T> findAll(Class<T> entityType)

次に、クラスで呼び出すことができます:

findAll(String.class)

コンパイラは、それが を返すことになっていることを自動的に検出しますList<String>。冗長性を減らしますが、その逆ではなく、クラスから型引数を推論します。これは、この種の問題を解決する標準的な方法です。Guavaなどのライブラリでよく使われます。

于 2012-06-21T21:02:14.557 に答える
1

「ジェネリックDAO」を作成するための標準的な方法は、パラメーター化可能な抽象クラスを持ち、特定のパラメーターを持つサブクラスを持つことです。このようにして、メソッド自体はすでに正しいタイプでパラメーター化されています。

例としてこれを見てください:

http://netbeans.org/projects/samples/sources/samples-source-code/content/samples/javaee/AffableBean/src/java/session/AbstractFacade.java

于 2012-06-21T20:58:06.690 に答える
1

そうではありません。ジェネリックはコンパイル時の機能です。実行時に、API の呼び出し元はClass<T>for entityType の任意のインスタンスを提供できるため、休止状態に提供するために実行時に利用できる必要があります。コンパイラには、可能なすべてのT.

また、Class生の型であり、すでにジェネリックを不適切に使用しています;)

于 2012-06-21T20:59:29.773 に答える
1

Java は型消去を使用します。つまり、ジェネリック型パラメーターは実行時に使用できません (コードが型に関して正しいことを保証するためにコンパイル時に使用されます)。これは、持続性を使用するには、クラスを明示的に渡す必要があることを意味します。これにより、ランタイムは持続性を実行する方法 (例えば、持続するオブジェクトが属するクラス) を把握できます。

于 2012-06-21T20:59:38.297 に答える
1

簡単な答えは「いいえ」です。Object.class型消去と呼ばれるものにより、すべてのパラメーター化された型は、コンパイルされたバイトコードで実行時に扱われます。ジェネリック型は、間違った使用を防ぐためにコンパイル時にのみ使用されます。

于 2012-06-21T21:03:32.907 に答える
0

求めていることは多かれ少なかれ Scala で行うことができます。(scalaが使えるかどうかはわかりませんが、参考までに、ここにあります)。

object Main extends App{
    def findAll[T : Manifest]() : Array[T] = {
       var a = new Array[T](0)
       println(a.getClass)
       a
    }

    var result = findAll[String]()
    println(result.getClass)

    var result2 = findAll[Array[Int]]()
    println(result2.getClass)
}

暗黙的な Manfiest を使用することにより、scala コンパイラは、コンパイル時にどのジェネリックが消去されるかを記録します。

于 2012-06-21T21:27:03.317 に答える