rt,代码逻辑大概是这样:
public class MyFactoryBean implements FactorBean<MyBean> { private String myProperty; public void setMyProperty(String myProperty) { this.myProperty = myProperty; } @Override public MyBean getObject() throws Exception { return createBean(); } public MyBean createBean(){ MyBean myBean = new MyBean(); myBean.setProperty(myProperty); //下面 UserListener 调试时,UserListener 对象的类型是“MyFactoryBean$$Lambda$400/0x0000000800e9b558@4225” UserListener<User1> userListener=new UserListener<User1>(){ @Override public void active(){ //doSomething } }; Cache.addUserListener(userListener); return myBean; } @Override public Class<?> getObjectType() { return MyBean.class; } @Override public boolean isSingleton() { return true; } }
UserListener
时,发现传递的不是 UserListener 实例的具体类型(UserListener 是一个泛型接口),而是一个MyFactoryBean$$Lambda$400/0x0000000800e9b558@4225
代理对象,请问有什么方式能直接得到该类具体的类型吗?除了把对象类型一并传过去
Cache.addUserListener(userListener,User1.class);
哈哈,问了下chatgpt,它说runtime时没法直接得到这个泛型,提供的思路跟我说的基本一样,就是在添加时,把类型传过去。
I understand. In Java, due to type erasure, it is not possible to directly obtain the type parameter T at runtime. However, you can work around this limitation by passing a Class<T> object as a parameter to the addUserListener method. Here's an example of how you can modify the Cache class to achieve this: public class Cache { public static <T extends User> void addUserListener(UserListener<T> userListener, Class<T> userType) { // implementation of the method goes here System.out.println("User type is: " + userType.getSimpleName()); } }
1 letsky 2023-05-21 10:33:12 +08:00 试试 Spring 的这个类,https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/ResolvableType.html ```java private HashMap<Integer, List<String>> myMap; public void example() { ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap")); t.getSuperType(); // AbstractMap<Integer, List<String>> t.asMap(); // Map<Integer, List<String>> t.getGeneric(0).resolve(); // Integer t.getGeneric(1).resolve(); // List t.getGeneric(1); // List<String> t.resolveGeneric(1, 0); // String } ``` |
![]() | 2 luckykev1n 2023-05-21 11:27:18 +08:00 不考虑 spring 的话,可以用反射 public class Main { public static void main(String[] args) { UserListener<String> userListener = new UserListener<String>() {}; // 获取实际类型 Class<? extends UserListener> listenerClass = userListener.getClass(); // 获取实际范型 Type[] interfaces = listenerClass.getGenericInterfaces(); Type listenerType = interfaces[0]; ParameterizedType paraType = (ParameterizedType) listenerType; Type[] actualTypes = paraType.getActualTypeArguments(); Class<?> actualType = (Class<?>) actualTypes[0]; // 打印实际范型 System.out.println(actualType); } } |
![]() | 3 luckykev1n 2023-05-21 11:30:56 +08:00 1 楼的这个 ResolvableType ,其实也是 Spring 基于 java 的反射实现的, ``` public ResolvableType[] getGenerics() { if (this == NONE) { return EMPTY_TYPES_ARRAY; } if (this.generics == null) { if (this.type instanceof Class) { Class<?> typeClass = (Class<?>) this.type; this.generics = forTypes(SerializableTypeWrapper.forTypeParameters(typeClass), this.variableResolver); } else if (this.type instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) this.type).getActualTypeArguments(); ResolvableType[] generics = new ResolvableType[actualTypeArguments.length]; for (int i = 0; i < actualTypeArgments.length; i++) { generics[i] = forType(actualTypeArguments[i], this.variableResolver); } this.generics = generics; } else { this.generics = resolveType().getGenerics(); } } return this.generics; } |
![]() | 4 OldCarMan OP @letsky 谢谢回复 @luckykev1n 谢谢回复,你 2 楼回复的: ParameterizedType paraType = (ParameterizedType) listenerType; 类型无法转换( java.lang.ClassCastException: class java.lang.Class cannot be cast to class java.lang.reflect.ParameterizedType )。 1. ![]() 2. ![]() 3. ![]() 可能我没描述好,我说的是,我在另外一个类 Cache.java 里面接收 UserListener 时,无法获取到泛型接口 UserListener<T extends User>相应的泛型 T 类型: public class Cache{ ----- public static void addUserListener(UserListener<T extends User> userListener){ 在这里无法直接获取得到 userListener 的相应的泛型 T 类型 } ----- } |