【问题标题】:Creating a cache of generic objects创建通用对象的缓存
【发布时间】:2018-07-29 18:46:04
【问题描述】:

我需要创建通用对象的 Java 缓存。我正在尝试执行以下操作,但这不会编译。

public class Example<T> {

  public static class ExampleCache {
    private Map<String, Example<?>> cache = new ConcurrentHashMap<>();

    public <T> Example<T> getExample(String name) {
      return cache.computeIfAbsent(name, k -> new Example<T>());
    }
  }
}

带有cache.computeIfAbsent 的行会产生错误

"Error:(16, 35) java: incompatible types: Example<capture#1 of ?> cannot be converted to Example<T>

有什么建议吗?

【问题讨论】:

    标签: java generics caching


    【解决方案1】:

    您尝试做的不是输入安全。
    您可以将? 转换为T,但这不是类型安全的:

    return (Example<T>) cache.computeIfAbsent(name, k -> new Example<T>());
    

    您希望getExample() 的客户端决定返回的Exemple 实例的泛型类型。
    假设您添加为条目"hello"-"Example&lt;String&gt;",并且客户端以这种方式调用getExample()Example&lt;Integer&gt; example : getExample("hello");,他/她将有一个不正确的泛型类型,它可能会在运行时引发一些不一致/异常。

    事实上,ExampleCache 与它作为输入/输出的泛型类型不一致。
    因此,要么将通配符替换为 T 以定义特定类型的 ExampleCache,要么像在客户端类中一样在缓存中仅使用 Example&lt;?&gt;,或者仍然不为 Example 类使用泛型。

    【讨论】:

      【解决方案2】:

      这是因为类型 T 与通配符 ? 不兼容。编译器如何知道Example&lt;T&gt; 将从值映射Example&lt;?&gt; 中接收?您必须使用强制转换或更好地将类型应用于静态类:

      public class Example<T> {
      
          public static class ExampleCache<T> {
      
              private Map<String, Example<T>> cache = new ConcurrentHashMap<>();
      
              public Example<T> getExample(String name) {
                  return cache.computeIfAbsent(name, k -> new Example<>());
              }
          }
      }
      

      如果你没有在ExampleCache 中包含类型,则会抛出错误:

      无法对非静态类型 T 进行静态引用

      仅当ExampleCache 不是staticExampleCache 的实例将被固定为Example&lt;T&gt; 的实例时才有效。欲了解更多信息,请阅读Java generics with class and nested static interface

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-12
        • 2011-08-06
        • 2020-02-12
        • 2019-09-04
        • 2019-06-11
        • 2015-01-08
        • 2011-03-16
        • 2015-03-24
        相关资源
        最近更新 更多