由于Java泛型,我无法编译Guava的Cache的构建器

Oli*_*ire 3 java generics guava

我有以下简短的自包含代码,在编译时显示错误.我拼命想要编译它.我通常不再遇到仿制药了,但是我放弃了这个,我请求团队的帮助.

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

无法编译的行是:

return new ResourceType<? extends Resource<?>>(key);
Run Code Online (Sandbox Code Playgroud)

我知道它失败的原因:我可能不会new Xxxx<...>用问号(?)写.我不能以不同的方式编写这一行来编译其他行.

我有一个后备解决方案,在Resource没有泛型的情况下,但在可能的限制,我想Resource与泛型保持一致.

我对其中的泛型没有任何限制,LoadingCache除了我需要它被称为getResourceType(Class).

那么......我该如何修复这段代码呢?

gon*_*ard 5

一个忽略警告的解决方案:

  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);
        }
    });
Run Code Online (Sandbox Code Playgroud)

正如@John B在评论中所建议的那样 .由于类型擦除,此代码在运行时与问题中的代码没有区别.

  • 作为一个补充点,由于类型擦除,上述在运行时与问题中的代码没有区别,因此没有理由不使用它. (3认同)
  • 与原始类型一样令人反感,它们在这里可能是一种可接受的方法.为了使缓存具有静态类型安全性,它需要在泛型系统根本无法表达的键和值之间存在约束,因此仅使用"不使用"泛型是有意义的. (2认同)