rt,代码逻辑大概是这样:
public class MyFactoryBean implements FactoryBean<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 < actualTypeArguments.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 类型 } ----- } |