Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?
java.util.Properties是 的一个实现java.util.Map,并且java.util.HashMap的构造函数接收一个Map类型参数。那么,为什么必须显式转换呢?
Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?
java.util.Properties是 的一个实现java.util.Map,并且java.util.HashMap的构造函数接收一个Map类型参数。那么,为什么必须显式转换呢?
这是因为PropertiesextendsHashtable<Object, Object>(反过来,实现Map<Object, Object>)。您尝试将其输入到Map<String, String>. 因此是不兼容的。
您需要将字符串属性一一输入到地图中......
例如:
for (final String name: properties.stringPropertyNames())
    map.put(name, properties.getProperty(name));
    做到这一点的有效方法就是转换为通用 Map 如下:
Properties props = new Properties();
Map<String, String> map = (Map)props;
这会将 a 转换Map<Object, Object>为原始 Map,这对于编译器来说是“可以的”(仅警告)。一旦我们有了一个 raw Map,它就会被转换成Map<String, String>它也将是“好的”(另一个警告)。您可以使用注释忽略它们@SuppressWarnings({ "unchecked", "rawtypes" })
这将起作用,因为在 JVM 中,对象实际上并没有泛型类型。泛型类型只是在编译时验证事物的一种技巧。
如果某个键或值不是字符串,则会产生ClassCastException错误。在当前的Properties实现中,这不太可能发生,只要您不Hashtable<Object,Object>使用Properties.
所以,如果不要对你的 Properties 实例做讨厌的事情,这就是要走的路。
您可以使用 Google Guava 的:
这个怎么样?
   Map properties = new Properties();
   Map<String, String> map = new HashMap<String, String>(properties);
将导致警告,但无需迭代即可工作。
Java 8 方式:
properties.entrySet().stream().collect(
    Collectors.toMap(
         e -> e.getKey().toString(),
         e -> e.getValue().toString()
    )
);
    Properties实现Map<Object, Object>- 不是Map<String, String>。
您正在尝试调用此构造函数:
public HashMap(Map<? extends K,? extends V> m)
... withK和Vboth as String。
但Map<Object, Object>is not a Map<? extends String, ? extends String>... 它可以包含非字符串键和值。
这会起作用:
Map<Object, Object> map = new HashMap<Object, Object>();
...但它不会对你有用。
从根本上说,Properties永远不应该成为HashTable......的子类,这就是问题所在。从 v1 开始,它总是能够存储非字符串键和值,尽管这违背了本意。如果改为使用组合,API 可能只能使用字符串键/值,一切都会很好。
你可能想要这样的东西:
Map<String, String> map = new HashMap<String, String>();
for (String key : properties.stringPropertyNames()) {
    map.put(key, properties.getProperty(key));
}
    我会使用以下番石榴 API: com.google.common.collect.Maps#fromProperties
Properties properties = new Properties();
Map<String, String> map = Maps.fromProperties(properties);
    如果您知道您的Properties对象仅包含<String, String>条目,则可以使用原始类型:
Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>((Map) properties);
    问题在于Properties实现Map<Object, Object>,而HashMap构造函数需要一个Map<? extends String, ? extends String>.
这个答案解释了这个(非常违反直觉的)决定。简而言之:在 Java 5 之前Properties实现Map(因为当时没有泛型)。这意味着您可以将任何 Object内容放入Properties对象中。这仍在文档中:
因为
Properties继承自Hashtable,put和putAll方法可以应用于Properties对象。强烈建议不要使用它们,因为它们允许调用者插入键或值不是Strings 的条目。setProperty应该改用该方法。
为了保持与此的兼容性,设计者别无选择,只能Map<Object, Object>在 Java 5 中继承它。这是努力实现完全向后兼容性的不幸结果,这使得新代码不必要地复杂化。
如果您只在Properties对象中使用字符串属性,您应该能够在构造函数中使用未经检查的强制转换:
Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);
或没有任何副本:
Map<String, String> map = (Map<String, String>) properties;
    这只是因为 HashMap 的构造函数需要 Map 泛型类型的 arg 并且 Properties 实现了 Map。
这将起作用,但会发出警告
    Properties properties = new Properties();
    Map<String, String> map = new HashMap(properties);
    你可以使用这个:
Map<String, String> map = new HashMap<>();
props.forEach((key, value) -> map.put(key.toString(), value.toString()));
    第一件事,
属性类基于 Hashtable 而不是 Hashmap。属性类基本上扩展了 Hashtable
HashMap 类中没有这样的构造函数,它接受一个属性对象并返回一个 hashmap 对象。所以你在做什么是不正确的。您应该能够将属性对象转换为哈希表引用。
当我看到Spring框架源代码时,我发现了这种方式
Properties props = getPropertiesFromSomeWhere();
 // change properties to map
Map<String,String> map = new HashMap(props)
    我用这个:
for (Map.Entry<Object, Object> entry:properties.entrySet()) {
    map.put((String) entry.getKey(), (String) entry.getValue());
}