web-dev-qa-db-ja.com

Javaジェネリックス:ジェネリックメソッドの戻り値の型のクラスを取得する

バックグラウンド

私はかつてこの方法を書いた:

_private <T> SortedSet<T> createSortedSet() {
  return new TreeSet<T>();
}
_

このように呼ばれることになっています:

_Set<String> set = createSortedSet();
_

これは正常に動作します(ただし、これはエラーが発生しやすいという現在の質問を調査したときの回答で確認しました)。

現状

とにかく、今は次のコードを記述しています(javax.servlet.jsp.tagext.TagSupportを拡張するクラス):

_private <T> T evaluate(String expression) {
  ExpressionEvaluator evaluator = pageContext.getExpressionEvaluator();
  return evaluator.evaluate(expression, T, null, pageContext.getVariableResolver());
}
_

目的はこれを次のように呼び出せるようにすることです:

_Integer width = evaluate(widthStr);
_

私のevaluateメソッドのコードは明らかに機能しません。 evaluator.evaluate()の2番目の引数はClassオブジェクトであると想定されています。これは私を導きます:

私の質問

ジェネリック(戻り)タイプのクラスを取得するにはどうすればよいですか?評価する2番目の引数としてTの代わりに何を書けばよいですか?

編集:結論

Nicolasは正しいようですが、実行できません。クラスを引数としてメソッドに渡す必要があります。良い点は、彼の解決策が引数をジェネリック型でパラメーター化するため、その引数のコンパイルチェックが行われることです。

33
Peter Jaric

残念ながら、メソッドを次のように変更する必要があります。

private <T> T evaluate(Class<T> clazz, String expression)

次に、2番目のパラメーターとしてclazzを渡します。期待したほど短くはありません。

47
Nicolas

最初に汎用オブジェクトを作成してから、そのパラメーター化された型を取得できます。

private <T> T evaluate(String expression) {
  List<T> dummy = new ArrayList<>(0);
  Type[] actualTypeArguments = ((ParameterizedType) dummy.getClass().getGenericSuperclass()).getActualTypeArguments();
  Type clazz = actualTypeArguments[0];
  Class<T> theClass = (Class<T>) clazz.getClass();

  ExpressionEvaluator evaluator = pageContext.getExpressionEvaluator();
  return evaluator.evaluate(expression, theClass, null, pageContext.getVariableResolver());
}

注意してください!あなたはClass<>オブジェクトの場合、動作が異なるTypeVariableImplサブクラスオブジェクトを取得します。

0