Downcasting Guava 地图 类
Downcasting Guava map classes
我在一个使用
番石榴数据类型的系统上工作了大约一个月
ImmutableMap<String, Object>
一切都很好,甚至我的开发人员也喜欢它。这很棒。直到昨天。我们有一个记录集,我们必须将其作为 ImmutableListMultimap 引入,并且我们必须将其转换为我们的 ImmutableMap 类型。
这是我们的编译错误
ImmutableListMultimap<String, Object> tst = new bla bla bla;
ImmutableMap<String, Object> tst2 = (ImmutableMap<String, Object>) tst.asMap();
错误本身是
Cannot cast from ImmutableMap<String,Collection<Object>> to ImmutableMap<String,Object>
现在做这个演员不是一个选择。它必须完成,否则我们必须回去重新设计一个月的工作。不会发生。我现在解决这个问题的唯一选择是建立一个工厂 class 来迭代 tst
变量,将值重新转换为基本对象并将其转储到 tst2
中。但是,这个 tst var 可能包含数千个条目,这使得该解决方案不明智。
另一个选项是 Apache Collections Transforms,但由于它们也只是迭代器,所以我没有太多收获。
有什么更优雅的方法可以让泛型转型,或者 Sun 的泛型类型擦除的绝妙概念注定了我。
它不能强制转换是有充分理由的,但有一个简单的解决方法:
ImmutableMap<String, Object> tst2 =
(ImmutableMap<String, Object>) (Object) tst.asMap();
这看起来可能更理智:
ImmutableListMultimap<String, Object> tst = ...
ImmutableMap<String, ? extends Collection<Object>> asMap = tst.asMap();
@SuppressWarnings("unchecked")
ImmutableMap<String, Object> tst2 = (ImmutableMap<String, Object>) asMap;
通用系统并不完美(如果完美的话,它会更复杂),有时很难理解。由于不变性,上面未经检查的转换是安全的:无法放入 Object
(这会违反 Map<String, Collection<Object>>
签名)。
您可以使用 ImmutableMap.copyOf
方法,具有显式约束:
ImmutableMap<String, Object> tst2 = ImmutableMap.<String, Object>copyOf(tst.asMap());
请注意,此 doesn't necessarily copy the map - 在某些(许多)情况下,tst == tst2
(它们是相同的引用)。
如果您绝对必须避免复制地图,则需要使用通配符类型,因为 ImmutableMap<K, Object>
和 ImmutableMap<K, Collection<Object>>
不是相关类型:
ImmutableMap<String, ?> tst2 = tst.asMap();
值是通配符类型这一事实不应影响您对映射值执行任何操作的能力,如 Object
s:
for (Map.Entry<String, ?> entry : tst2.entrySet()) {
Object value = entry.getValue();
//...
}
因此,一种不会生成任何编译警告的方法是使用 ImmutableMap.copyOf
而不是强制转换。这实际上不会执行复制,因为它可以检测到这是多余的,但它需要一个 ImmutableMap<? extends K, ? extends V>
和 return 一个 ImmutableMap<K, V>
.
它仍然是一个常量时间操作,并且在表面下进行转换,但不会产生警告。
我在一个使用
番石榴数据类型的系统上工作了大约一个月ImmutableMap<String, Object>
一切都很好,甚至我的开发人员也喜欢它。这很棒。直到昨天。我们有一个记录集,我们必须将其作为 ImmutableListMultimap 引入,并且我们必须将其转换为我们的 ImmutableMap 类型。
这是我们的编译错误
ImmutableListMultimap<String, Object> tst = new bla bla bla;
ImmutableMap<String, Object> tst2 = (ImmutableMap<String, Object>) tst.asMap();
错误本身是
Cannot cast from ImmutableMap<String,Collection<Object>> to ImmutableMap<String,Object>
现在做这个演员不是一个选择。它必须完成,否则我们必须回去重新设计一个月的工作。不会发生。我现在解决这个问题的唯一选择是建立一个工厂 class 来迭代 tst
变量,将值重新转换为基本对象并将其转储到 tst2
中。但是,这个 tst var 可能包含数千个条目,这使得该解决方案不明智。
另一个选项是 Apache Collections Transforms,但由于它们也只是迭代器,所以我没有太多收获。
有什么更优雅的方法可以让泛型转型,或者 Sun 的泛型类型擦除的绝妙概念注定了我。
它不能强制转换是有充分理由的,但有一个简单的解决方法:
ImmutableMap<String, Object> tst2 =
(ImmutableMap<String, Object>) (Object) tst.asMap();
这看起来可能更理智:
ImmutableListMultimap<String, Object> tst = ...
ImmutableMap<String, ? extends Collection<Object>> asMap = tst.asMap();
@SuppressWarnings("unchecked")
ImmutableMap<String, Object> tst2 = (ImmutableMap<String, Object>) asMap;
通用系统并不完美(如果完美的话,它会更复杂),有时很难理解。由于不变性,上面未经检查的转换是安全的:无法放入 Object
(这会违反 Map<String, Collection<Object>>
签名)。
您可以使用 ImmutableMap.copyOf
方法,具有显式约束:
ImmutableMap<String, Object> tst2 = ImmutableMap.<String, Object>copyOf(tst.asMap());
请注意,此 doesn't necessarily copy the map - 在某些(许多)情况下,tst == tst2
(它们是相同的引用)。
如果您绝对必须避免复制地图,则需要使用通配符类型,因为 ImmutableMap<K, Object>
和 ImmutableMap<K, Collection<Object>>
不是相关类型:
ImmutableMap<String, ?> tst2 = tst.asMap();
值是通配符类型这一事实不应影响您对映射值执行任何操作的能力,如 Object
s:
for (Map.Entry<String, ?> entry : tst2.entrySet()) {
Object value = entry.getValue();
//...
}
因此,一种不会生成任何编译警告的方法是使用 ImmutableMap.copyOf
而不是强制转换。这实际上不会执行复制,因为它可以检测到这是多余的,但它需要一个 ImmutableMap<? extends K, ? extends V>
和 return 一个 ImmutableMap<K, V>
.
它仍然是一个常量时间操作,并且在表面下进行转换,但不会产生警告。