Как получить простое универсальное имя типа?

Я хочу получить строковое представление возвращаемого типа метода с аргументами типа, но без имени пакета, например «Список».

Из объекта класса возвращаемого типа мы можем получить простое имя без префикса пакета через method.getReturnType().getSimpleName(), но без параметров типа дженериков. Выход: List

Также возможно получить аргументы универсального типа в длинной форме через method.getGenericReturnType().toString(). Выход: java.util.collections.List<java.util.String>

Но как получить простое имя с аргументами универсального типа?

Например: List<String> вместо java.util.collections.List<java.util.String>

вы можете разделить его на "." (точка) и прочитать последний индекс.

Khalid Shah 04.04.2019 11:07

есть метод getSimpleName(), попробуй

Ravi 04.04.2019 11:08

+ Предупреждение: java.util.String лексически совпадает с com.anees.String

Mohamed Anees A 04.04.2019 11:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
419
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете пройтись по дереву типов, используя такой простой метод:

  static String simpleTypeName(Type t) {
    if (t instanceof ParameterizedType) {
      ParameterizedType p = (ParameterizedType) t;
      return simpleTypeName(p.getRawType())
          + Stream.of(p.getActualTypeArguments())
              // Recurse to handle the type arguments.
              .map(YourClass::simpleTypeName)
              .collect(Collectors.joining(", ", "<", ">"));
    } else if (t instanceof Class) {
      Class<?> c = (Class<?>) t;
      return c.getSimpleName();
    } else {
      // ... handle other Type subtypes.
    }
  }

и вызывать как:

String typeName = simpleTypeName(yourMethod.getGenericReturnType());

Ideone demo

@MohamedAneesA, но автор намеренно не хочет иметь пакеты, так что это не должно быть проблемой.

Michał Ziober 04.04.2019 11:54

@MohamedAneesA, теперь вы можете удалить свои комментарии здесь :)

Andy Turner 04.04.2019 12:09
Ответ принят как подходящий

Вам нужно написать простой класс, который рекурсивно проходит тип и генерирует простое имя на каждом уровне:

class TypeSimpleName {

    private final Type value;

    public TypeSimpleName(Type value) {
        this.value = value;
    }

    public String getName() {
        return getName(value);
    }

    private String getName(Type type) {
        if (type instanceof ParameterizedType) {
            return getParameterizedTypeName((ParameterizedType) type);
        }
        if (type instanceof Class) {
            return getClassSimpleName(type);
        }
        // handle other types if needed

        return type.getTypeName();
    }

    private String getParameterizedTypeName(ParameterizedType type) {
        StringBuilder builder = new StringBuilder();

        builder.append(getName(type.getRawType()));
        Type[] typeArguments = type.getActualTypeArguments();
        if (typeArguments.length > 0) {
            builder.append("<");
            for (int i = 0; i < typeArguments.length; i++) {
                Type arg = typeArguments[i];
                builder.append(getName(arg));
                if (i < typeArguments.length - 1) {
                    builder.append(", ");
                }
            }
            builder.append(">");
        }

        return builder.toString();
    }

    private String getClassSimpleName(Type type) {
        return ((Class) type).getSimpleName();
    }

    @Override
    public String toString() {
        return getName();
    }
} 

Как это использовать:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.util.ReflectionUtils;

public class Test {

    public static void main(String[] args) {
        System.out.println(getReturnTypeName("getList"));
        System.out.println(getReturnTypeName("getListList"));
        System.out.println(getReturnTypeName("getObj"));
        System.out.println(getReturnTypeName("getMapMap"));
    }

    private static String getReturnTypeName(String method) {
        Type returnType = ReflectionUtils.findMethod(Test.class, method).getGenericReturnType();

        return new TypeSimpleName(returnType).getName();
    }

    public List<String> getList() {
        return null;
    }

    public List<List<String>> getListList() {
        return null;
    }

    public Integer getObj() {
        return 1;
    }

    public Map<String, Map<Integer, BigDecimal>> getMapMap() {
        return null;
    }
}

Над кодом печатается:

List<String>
List<List<String>>
Integer
Map<String, Map<Integer, BigDecimal>>

Другие вопросы по теме