我能';t编译番石榴';s缓存&x27;因为Java泛型,所以使用了s builder
我有以下简短、自包含的代码,显示编译时的错误。我拼命想把它编译一下。我通常不会再遇到泛型的问题,但是我放弃了这个,我请求团队的帮助我能';t编译番石榴';s缓存&x27;因为Java泛型,所以使用了s builder,java,generics,guava,Java,Generics,Guava,我有以下简短、自包含的代码,显示编译时的错误。我拼命想把它编译一下。我通常不会再遇到泛型的问题,但是我放弃了这个,我请求团队的帮助 import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; public class CacheWithGenericsDoesNotCompile {
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
public class CacheWithGenericsDoesNotCompile {
// Class definition can't be modified
static class Resource<T extends Resource<T>> {}
// Class definition can't be modified
static class ResourceType<T extends Resource<T>> {
public ResourceType(Class<T> type) {}
}
// Variable definition may be modified
static LoadingCache<Class<? extends Resource<?>>, ResourceType<? extends Resource<?>>> cache = CacheBuilder.newBuilder().build(
new CacheLoader<Class<? extends Resource<?>>, ResourceType<? extends Resource<?>>>() {
@Override public ResourceType<? extends Resource<?>> load(Class<? extends Resource<?>> key) throws Exception {
return new ResourceType<? extends Resource<?>>(key);
}
});
// Method definition can't be modified, method content may.
@SuppressWarnings("unchecked")
static <T extends Resource<T>> ResourceType<T> getResourceType(Class<T> type) {
return (ResourceType<T>)cache.getUnchecked(type);
}
}
import com.google.common.cache.CacheBuilder;
导入com.google.common.cache.CacheLoader;
导入com.google.common.cache.LoadingCache;
带有GenericsDoetCompile的公共类缓存{
//无法修改类定义
静态类资源{}
//无法修改类定义
静态类资源类型{
公共资源类型(类类型){}
}
//可以修改变量定义
静态加载缓存>>cache=CacheBuilder.newBuilder().build(
新缓存加载程序>>(){
@重写公共资源类型>加载(类>键)引发异常{
返回新的ResourceType>(键);
}
});
//无法修改方法定义,可能会修改方法内容。
@抑制警告(“未选中”)
静态ResourceType getResourceType(类类型){
return(ResourceType)cache.getUnchecked(type);
}
}
未能编译的行是:
return new ResourceType<? extends Resource<?>>(key);
返回新的ResourceType>(键);
我知道它失败的原因:我可能不会写带有问号(?
)的新Xxxx
。我只是不能把这一行写得和其他行不一样
在Resource
没有泛型的情况下,我有一个后备解决方案,但在可能的范围内,我希望Resource
使用泛型
我对LoadingCache
的泛型没有任何限制,只是需要在getResourceType(Class)
中调用它
所以。。。如何修复此代码?带有一些忽略警告的解决方案:
static LoadingCache<Class<? extends Resource<?>>, ResourceType<? extends Resource<?>>> cache = CacheBuilder.newBuilder().build(
new CacheLoader<Class<? extends Resource<?>>, ResourceType<? extends Resource<?>>>() {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override public ResourceType<? extends Resource<?>> load(Class<? extends Resource<?>> key) throws Exception {
return new ResourceType(key);
}
});
static LoadingCache>>cache=CacheBuilder.newBuilder().build(
新缓存加载程序>>(){
@SuppressWarnings({“rawtypes”,“unchecked”})
@重写公共资源类型>加载(类>键)引发异常{
返回新的ResourceType(键);
}
});
正如作者在评论中所建议的那样。这段代码在运行时与问题中的代码没有什么不同,因为。我更多地使用了gontard的解决方案(因此,如果您对此进行了投票,请确保也对gontard的答案进行投票)和millimoose的评论。我找到了这个解决方案,它完全删除了泛型,以获得更可读的代码
@SuppressWarnings("rawtypes")
static LoadingCache<Class, ResourceType> cache = CacheBuilder.newBuilder().build(
new CacheLoader<Class, ResourceType>() {
@SuppressWarnings("unchecked")
@Override public ResourceType load(Class key) throws Exception {
return new ResourceType(key);
}
});
@SuppressWarnings(“rawtypes”)
静态加载缓存=CacheBuilder.newBuilder().build(
新缓存加载程序(){
@抑制警告(“未选中”)
@重写公共资源类型加载(类键)引发异常{
返回新的ResourceType(键);
}
});
如果我们能将键
转换成合适的类型
Class<T> for some T that T<:Resource<T>
Class对于一些添加了点的T,由于类型擦除,上面的代码在运行时与问题中的代码没有区别,因此没有理由不使用它。是的,它编译并执行任务。谢谢尽管原始类型令人厌恶,但它们可能是一种可以接受的方法。为了使缓存是静态类型安全的,它需要在键和值之间有一个约束,而泛型系统根本无法表达这些约束,因此“不使用”泛型是有意义的。啊,我缺少的是递归边界(t extensed Resource
)由于通配符捕获的限制而丢失,这就是我的答案不起作用的原因。
ResourceType<? extends Resource<?>> result = new ResourceType<>(casted_key)