[英]Java generic method type argument
我对泛型方法的显式类型参数有疑问。 我知道我可以这样做:
Foo.<Bar>function();
假设有一个
void <T> function() {...}
在Foo类中起作用。 确切的问题是:
我想下载一些内容(带有Ion的 Android)
这些内容相似(Article,BlogArticle等),都实现了ContentItem接口
目前下载如下:
例如新闻
private void downloadNews() {
Ion.with(this)
.load(URL_NEWS)
.as(new TypeToken<List<Article>>(){})
.setCallback(new FutureCallback<List<Article>>() {
@Override
public void onCompleted(Exception e, List<Article> result) {
// do something with result
}
});
}
如果要下载博客文章,则仅需更改url和Article类(对于BlogArticle)。
我试图做一个通用的函数是这样的:
private <T extends ContentItem> void download(String url) {
Ion.with(this)
.load(url)
.as(new TypeToken<List<T>>(){})
.setCallback(new FutureCallback<List<T>>() {
@Override
public void onCompleted(Exception e, List<T> result) {
// do something with result
}
});
}
并调用该函数
this.<Article>download(url);
可以,编译正常。 跑步后我得到
java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法转换为com.my.packagename.model.ContentItem
问题在于它没有使用显式类将Json映射到pojo。
您能建议我一个通用的解决方案吗?
我认为无法使用TypeToken方法以通用方式实现所需的内容。 实际上,请注意,要使类型标记起作用,您需要创建一个匿名内部类。 通过这样做,您可以有效地创建一个新的类文件,该类文件的超类型被实化为List<Article>
。 换句话说,就像您有以下声明一样:
class ArticleToken extends TypeToken<List<Article>> { ... }
如果您自己编写上述声明,则会观察到类文件ArticleToken.class在所谓的Signature
属性(请参阅JVMS )中跟踪泛型超类型。 因此,此技巧使您以后可以通过调用Class.getGenericSupertype
来访问此类通用超类型。 换句话说,这是假冒伪造的泛型的惯用法。
如果将代码转换为通用方法,并用类型变量T替换Article,则会发生以下情况:您创建的类型令牌如下所示:
class GenericToken extends TypeToken<List<T>> { ... }
因此,有关T的信息将按原样存储在类文件中,如果reflectiopn要求提供类型令牌的泛型超类,则只需TypeToken<List<T>>
而不是TypeToken<List<Article>>
d期望这会导致您遇到的问题。 完成这项工作所需的是真正的泛型泛型,其中在方法调用站点将T绑定到Article会影响new TypeToken<List<T>>
的运行时行为-但是令人遗憾的是,使用擦除泛型的Java并非如此。
几年后,但我认为这对某人可能有用。 我最终得到了一个更简单的解决方案。 它只是一个简单的截断版本,但您可以理解:
public static <T> void asList(Context context, String url, Class<T[]> clazz, final FutureCallback<List<T>> callback) {
Ion.with(context)
.load(url)
.as(clazz)
.setCallback(new FutureCallback<T[]>() {
@Override
public void onCompleted(Exception e, T[] result) {
callback.onCompleted(e, Arrays.asList(result));
}
});
}
并使用像:
asList(context, url, YourObject[].class, new FutureCallback<List<YourObject>>() {...});
为了反序列化实现ContentItem的各种类,我认为您将需要使用具有TypeAdapter的自定义GSON实例。
那使用呢
private <T implements ContentItem> void download(String url) {
....
the ContentItem interface, they do not the interface 由于这些类了ContentItem接口,因此它们不会该接口
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.