我能';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)