我有一个通用接口
public interface MessageCallback<T extends JsonModel> {
void onMessage(T t);
}
我想获得T的实例。 我找到了可以使用反射的解决方案
public static <T> Class<T> getGenericClass(Class actualClass, int index) {
ParameterizedType genericSuperclass = (ParameterizedType) actualClass.getGenericSuperclass();
// Get generic class
return (Class<T>) genericSuperclass.getActualTypeArguments()[index];
}
但是它引发异常。
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
我想知道有没有不使用反射的解决方案吗?
额外。我也找到了
class Foo<T> {
final Class<T> typeParameterClass;
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}
但仅适用于上课。我该如何解决我的问题?感谢您的回答。
如果您想知道它不是干净的Java。在Android中
答案 0 :(得分:1)
关于您的第一个代码,Class.getGenericSuperclass()
返回表示this
类的直接超类的类型,在您的情况下为Object
。
Class.getGenericInterfaces()
返回表示Type
类直接实现的接口的this
,这是检索{{ 1}}界面。
但这可能对您没有帮助,因为泛型类型将是在MessageCallback
接口:MessageCallback
中静态声明的类型,而不是在扩展该接口的子类声明中定义的类型。
关于第二个代码,您不必担心捕获泛型的参数是JsonModel
还是Class
。
例如,在通用类(例如Type
中声明的类型或在通用类(例如interface MessageCallback<T extends JsonModel>
的子类中声明的类型)是必需的类,因为参数化类型只能是MessageCallbackImpl extends MessageCallback<MyJsonModel>
es。因此,将通用类型的类型存储为Class
是完全有效的。
Class
类是Java中所有类型通用的超级接口类(原始类型,参数化类型,数组类型,类型变量和基本类型)
所以回到您的问题:您需要的是在运行时引用编译时定义的泛型类型的方法,而这种惯用语是实现此目的的经典方法:
Type
答案 1 :(得分:0)
您在正确的轨道上。 现在假设我们有一个通用接口,如您的示例所示:
public interface MessageCallback<T extends JsonModel> {
void onMessage(T t);
}
及其具体实现:
class FooMessage {}
public class MyMessageCallback
implements MessageCallback<FooMessage extends JsonModel> {
@Override
public void onMessage(FooMessage t) {
System.out.println("Received foo");
}
}
您要查找传递到通用接口MessageCallback
(在本例中为FooMessage
)中的类型。
我们可以使用反射来查找MyMessageCallback
实现的所有接口,并为每个接口检查它是否为通用接口,然后返回其所有类型参数。
public static <T> Class<?>[] getGenericInterfaceParameter(Class clazz, Class<T> interfaceType) {
Class<?>[] result = new Class<?>[0];
// make sure interfaceType is a generic interface.
if(!interfaceType.isInterface() || interfaceType.getTypeParameters().length < 1) {
return result;
}
// get all interfaces implemented by concrete class.
Type[] interfaceTypes = clazz.getGenericInterfaces();
// for each interface the concrete class implements
// we check if that interface is actually equal to interfaceType
// and is a parametrized type,
// i.e has a type parameter.
// Once a match is found, we return the type parameters.
for(Type it : interfaceTypes) {
if(it instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) it;
if(!parameterizedType.getRawType().equals(interfaceType)) {
continue;
}
Type[] typeParameters = parameterizedType.getActualTypeArguments();
result = new Class[typeParameters.length];
for(int j = 0; j < typeParameters.length; j++) {
result[j] = (Class) typeParameters[j];
}
}
}
return result;
}
使用该方法查找MyMessageCallback
的类型参数:
Class<?>[] params = getGenericInterfaceParameter(
MyCallback.class,
MessageCallback.class
);
System.out.println(params[0].getTypeName()); // MyMessageCallback