具有复杂类型定义的Java Collections.synchronizedMap()

时间:2011-08-17 17:36:03

标签: java generics synchronization

假设我有一个类的类:

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

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

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

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

在该类的第4行,我收到错误“类型不匹配:无法从Map&lt; Set&lt; String&gt;,Object&gt;转换为MyMap&lt; String,Object&gt;”。 Eclipse建议我做两件事之一:向MyMap添加一个强制转换&lt; String,Object&gt;或将_myMap的类型更改为Map&lt;设置&lt; String&gt;,Object&gt;。但是,我显然不想做后者,因为使用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向下转换(?)为“true”类型,即Map&lt; SET&LT;字符串&gt;,对象&gt;&gt;,然后不允许我将其强制转换回MyMap,这是我传递给synchronizedMap()的类型。

有没有办法解决这些问题,使用synchronizedMap来处理这类课程?如果不是,那么推荐的实现外部或同步的方法是什么?

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

在完全不相关的旁注上,有没有人知道如何绕过奇怪的标签捕捉(这样我就不必像“Map&lt; K,V&gt;”那样放置空格),即使我用它封装它块?

2 个答案:

答案 0 :(得分:2)

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

至于你的问题的解决方案,我不是100%肯定你在寻找什么,但一个简单的ConcurrentHashMap是不够的?看一下javadocs的here

答案 1 :(得分:1)

问题是您将字段定义为“MyMap”。如果您打算使用外部同步,那么您必须只使用Map,以后甚至无法转换为MyMap。

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