我需要将泛型类传递给类的构造函数。该类是来自SpiceRequest Android库的RoboSpice,用于引用构造函数。
类似乎需要将泛型类传递给contstructor,这可能是从泛型类本身访问的,在本例中是RESULT.class
,但也许我错了。无论如何,我不打算更改库的代码,而是需要使用通用类型SpiceRequest
,Map<String, ? extends Object>
。这是我的代码:
SpiceRequest<Map<String, ? extends Object>> request =
new SpiceRequest<Map<String, ? extends Object>>(???) {
...
};
SpiceRequest
构造函数的签名:
public SpiceRequest(final Class<RESULT> clazz) {
...
}
对于???我尝试Map.class
编译错误:The constructor SpiceRequest<Map<String,? extends Object>>(Class<Map>) is undefined.
Map<String, ? extends Object>.class
提供错误:Syntax error on tokens, PrimitiveType expected instead
,特别强调? extends Object
。它也会出现与Map.class
相同的错误。
Map.<String, ? extends Object>class
也会产生相同的编译错误。
获取泛型类Class<Map<String, ? extends Object>>
的正确方法是什么?
答案 0 :(得分:5)
具体参数化类型或通配符参数化类型没有类文字。来自Angelika Langer's generics tutorial:
通配符参数化类型会丢失它们的类型参数 在名为 type erasure 的进程中转换为字节代码。作为一方 类型擦除的效果,泛型类型共享的所有实例化 相同的运行时表示,即相应的 raw的表示 输入的。换句话说,参数化类型没有类型 他们自己的代表。因此,没有意义 形成类文字,例如
List<?>.class
,List<? extends Number>.class
和List<Long>.class
,因为没有这样的Class
个对象 存在。只有原始类型List
具有代表其的Class
对象 运行时类型。它被称为List.class
。
由于相同的原因,具体参数化类型没有类文字,简而言之是type erasure。
出于您的目的,您只需要对类文字进行未经检查的强制转换:
Class<Map<String, ?>> c = (Class<Map<String, ?>>)(Class<?>)Map.class;
请注意,必须通过Class<?>
进行双重投放,因为从Class<Map>
到Class<Map<String, ?>>
的直接转换是非法的。
答案 1 :(得分:4)
这个问题与RoboSpice本身并没有实际关系,而是与Java语法的限制有关:没有可用于获取Java中参数化泛型类型的类/类型的文字。
如果你想做类似
的事情public class ListTweetRequest extends SpiceRequest<List<Tweet>> {
public ListTweetRequest(Object cacheKey ) {
super( <Here is the problem>, cacheKey );
}
}
然后你不能将类List<Tweet>.class
传递给你的父构造函数。这是一个Java限制,因为泛型是使用类型擦除实现的,List<Tweet>.class
在Java中没有实际意义。
最好和最干净的解决方法是使用类似的中间类型:
public class ListTweet extends List<Tweet> {
}
public class ListTweetRequest extends SpiceRequest<ListTweet> {
public ListTweetRequest(Object cacheKey ) {
super( ListTweet.class, cacheKey );
}
}
这样做的好处是可以为您提供一个可以传递给 SpiceRequest 构造函数的实际类型。但要注意混淆。在这种情况下,proguard将尝试删除ListTweet类,您必须明确地将其保留为模糊处理。
答案 2 :(得分:0)
我总是猜测擦除,但是你试过用Map.class调用它吗?
答案 3 :(得分:0)
我也遇到了这个问题,我找到了像@Snicolas这样的解决方案。
请看这个robospice-sample-reform的示例:
实际上最好不继承原始的List接口,而是继承任何子类,如ArrayList等,否则你将不得不实现所有的接口方法。
import java.util.ArrayList;
public class Contributor {
public String login;
public int contributions;
@SuppressWarnings("serial")
public static class List extends ArrayList<Contributor> {
}
}