【问题标题】:Java Collections.synchronizedMap() with complex type definition具有复杂类型定义的 Java Collections.synchronizedMap()
【发布时间】:2011-08-17 17:36:02
【问题描述】:

假设我有一个这样的类:

public class MyMap<K, V> implements Map<Set<K>, V> {
  ...
}

我希望能够对其强制同步。一种方法是在内部同步方法(可能使用同步关键字),但如果我打算将其用于更一般的用途,那么使用外部同步可能会更好,也许使用 Collections.synchronizedMap() 方法。

问题出现在我尝试实现这个的类中:假设我有以下类:

public class Foo {
  MyMap<String, Object> _myMap;
  public Foo() {
    _myMap = Collections.synchronizedMap(new MyMap<String, Object>());
  }
}

在课程的第 4 行,我收到错误“类型不匹配:无法从 Map, Object> 转换为 MyMap”。 Eclipse 建议我做以下两件事之一:要么向 MyMap 添加强制转换,要么将 _myMap 的类型更改为 Map, Object>。但是,我显然不想做后者,因为使用 MyMap 而不是 Map 的全部意义在于,我可以利用我在 MyMap 中实现的附加功能。然后,当我尝试按照他们的建议添加演员表时,现在该行看起来像

_myMap = (MyMap<String, Object>) Collections.synchronizedMap(new MyMap<String, Object>);

代码实际执行时出现以下错误:

java.lang.ClassCastException: java.util.Collections$SynchronizedMap cannot be cast to ****.MyMap

似乎 synchronizedMap() 正在向下转换(?) MyMap 到它的“真实”类型,即 Map, Object>>,然后不允许我将它转换回 MyMap,这是我传递给 synchronizedMap() 的类型。

有没有办法绕过这些来破解 synchronizedMap 以使用这种类?如果没有,实现外部或同步的推荐方法是什么?

也许作为一个后续问题,这种实现类型参数不是简单类型的接口的方法(例如第一个Map参数中的非平凡Set)在实践中是常用的吗?实现类(在这种情况下为 MyMap)是否可以用简单类型以外的任何东西进行参数化 - 换句话说,即使一个正在实现类似 Map&lt; Set&lt; K&gt;, V&gt; 的东西,实现类也可以有除 之外的东西吗?作为它的参数(尽管还有其他未使用的参数)?

在一个完全不相关的旁注中,有谁知道我如何绕过奇怪的标签捕获(这样我就不必放置像“Map”这样的空格),即使我用它括起来块?

【问题讨论】:

  • MyMap 做了哪些 HashMap、TreeMap、LinkedHashMap 没有做的事情?为什么需要一个特定的类而不是标准的 Map 接口?
  • 为什么FooMyMap 的构造函数?它应该是Foo 构造函数吗?
  • 忽必烈汗-很好,我的错字。 JB Nizet——如果你真的想知道,map 键是 Set 是有原因的——我之前的一个问题可能会为那些好奇的人提供更多的启示 :)。当然,如果 Java SDK 或 Google 的 Guava Collections 下的任何现有 Maps 实现了类似的目的,我会使用它们而不是尝试创建一个新的。
  • 为什么不直接使用 Map, Object>。为什么需要特定的自定义实现?

标签: java generics synchronization


【解决方案1】:

如果您查看 Collections.synchronizedMap 的 javadocs(请参阅 here),那么您将了解您实际上应该如何使用它以及它的作用。主要需要注意的是,您通过的 Map 被包装在 Map 的新同步实现中,并且此实现与 MyMap 不同,因此这就是显式转换失败的原因。

至于您的问题的解决方案,我不能 100% 确定您在寻找什么,但简单的 ConcurrentHashMap 是否不够?查看 here 的 javadocs。

【讨论】:

    【解决方案2】:

    问题是您将字段定义为“MyMap”。如果你打算使用外部同步,那么你必须只使用Map,以后你甚至不能投射到MyMap。

    原因是 SynchronizedMap 实际上不会“添加”同步到你的类,而是返回一个新的 Map 实现,同步,包装你作为参数传递的地图实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多