Я хочу получить строковое представление возвращаемого типа метода с аргументами типа, но без имени пакета, например «Список».
Из объекта класса возвращаемого типа мы можем получить простое имя без префикса пакета через method.getReturnType().getSimpleName(), но без параметров типа дженериков. Выход: List
Также возможно получить аргументы универсального типа в длинной форме через method.getGenericReturnType().toString(). Выход: java.util.collections.List<java.util.String>
Но как получить простое имя с аргументами универсального типа?
Например: List<String> вместо java.util.collections.List<java.util.String>
есть метод getSimpleName(), попробуй
+ Предупреждение: java.util.String лексически совпадает с com.anees.String




Вы можете пройтись по дереву типов, используя такой простой метод:
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());
@MohamedAneesA, но автор намеренно не хочет иметь пакеты, так что это не должно быть проблемой.
@MohamedAneesA, теперь вы можете удалить свои комментарии здесь :)
Вам нужно написать простой класс, который рекурсивно проходит тип и генерирует простое имя на каждом уровне:
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>>
вы можете разделить его на "." (точка) и прочитать последний индекс.