Обобщения Java: получить класс возвращаемого типа универсального метода - PullRequest
30 голосов
/ 18 ноября 2010

Фон

Я однажды написал этот метод:

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);

Код в моем методе оценки, очевидно, не работает. Второй аргумент evaluator.evaluate() должен быть объектом Class. Это приводит меня к:

Мой вопрос

Как я могу получить класс универсального (возвращаемого) типа? Что я должен написать вместо T в качестве второго аргумента для оценки?

РЕДАКТИРОВАТЬ: Заключение

Кажется, Николас прав, это невозможно, и мне нужно передать класс в качестве аргумента моему методу. Плюс в том, что, поскольку его решение делает аргумент параметризованным для универсального типа, я получаю проверку компиляции этого аргумента.

Ответы [ 2 ]

46 голосов
/ 18 ноября 2010

К сожалению, вам, безусловно, придется изменить свой метод на:

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

, а затем передать clazz в качестве второго параметра.Не так коротко, как вы ожидали.

0 голосов
/ 30 апреля 2019

Вы можете сначала создать универсальный объект, а затем получить его параметризованный тип:

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, который может вести себя по-разному.

...