Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?
java.util.Properties is a implement of Map, And HashMap constructor receive a Map type param. But why must convert explicitly?
java.util。属性是Map的实现,HashMap构造函数接收映射类型param。但是为什么要显式转换?
11 个解决方案
#1
68
This is because Properties
extends Hashtable<Object, Object>
(which, in turn, implements Map<Object, Object>
). You attempt to feed that into a Map<String, String>
. It is therefore incompatible.
这是因为属性扩展了Hashtable ,>
You need to feed string properties one by one into your map...
您需要将字符串属性逐一输入到您的映射中……
For instance:
例如:
for (final String name: properties.stringPropertyNames())
map.put(name, properties.getProperty(name));
#2
31
The efficient way to do that is just to cast to a generic Map as follows:
这样做的有效方法是将其转换为一个泛型映射,如下所示:
Properties props = new Properties();
Map<String, String> map = (Map)props;
This will convert a Map<Object, Object>
to a raw Map, which is "ok" for the compiler (only warning). Once we have a raw Map
it will cast to Map<String, String>
which it also will be "ok" (another warning). You can ignore them with annotation @SuppressWarnings({ "unchecked", "rawtypes" })
这将把Map
This will work because in the JVM the object doesn't really have a generic type. Generic types are just a trick that verifies things at compile time.
这将起作用,因为在JVM中对象并没有真正的泛型类型。泛型类型只是在编译时验证事物的一个技巧。
If some key or value is not a String it will produce a ClassCastException
error. With current Properties
implementation this is very unlikely to happen, as long as you don't use the mutable call methods from the super Hashtable<Object,Object>
of Properties
.
如果某个键或值不是字符串,它将产生ClassCastException错误。对于当前的属性实现,这是不可能发生的,只要您不使用超级Hashtable
So, if don't do nasty things with your Properties instance this is the way to go.
所以,如果你的属性实例不做龌龊的事情,这就是方法。
#3
25
How about this?
这个怎么样?
Map properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);
Will cause a warning, but works without iterations.
会引起警告,但不会迭代。
#4
20
You could use Google Guava's:
你可以用谷歌番石榴
com.google.common.collect.Maps.fromProperties(Properties)
com.google.common.collect.Maps.fromProperties(属性)
#5
14
Properties
implements Map<Object, Object>
- not Map<String, String>
.
属性实现Map
You're trying to call this constructor:
你要调用这个构造函数
public HashMap(Map<? extends K,? extends V> m)
... with K
and V
both as String
.
…K和V都是字符串。
But Map<Object, Object>
isn't a Map<? extends String, ? extends String>
... it can contain non-string keys and values.
但是Map
This would work:
这将工作:
Map<Object, Object> map = new HashMap<Object, Object>();
... but it wouldn't be as useful to you.
…但它对你没用。
Fundamentally, Properties
should never have been made a subclass of HashTable
... that's the problem. Since v1, it's always been able to store non-String keys and values, despite that being against the intention. If composition had been used instead, the API could have only worked with string keys/values, and all would have been well.
从根本上说,属性不应该被创建为HashTable的子类……这就是问题所在。自v1以来,它总是能够存储非字符串键和值,尽管这违背了意图。如果使用组合,那么API只能使用字符串键/值,而且所有的都很好。
You may want something like this:
你可能想要这样的东西:
Map<String, String> map = new HashMap<String, String>();
for (String key : properties.stringPropertyNames()) {
map.put(key, properties.getProperty(key));
}
#6
13
The Java 8 way:
Java 8道:
properties.entrySet().stream().collect(
Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue().toString()
)
);
#7
4
If you know that your Properties
object only contains <String, String>
entries, you can resort to a raw type:
如果您知道您的属性对象仅包含
Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>((Map) properties);
#8
4
The problem is that Properties
implements Map<Object, Object>
, whereas the HashMap
constructor expects a Map<? extends String, ? extends String>
.
问题是属性实现了Map
This answer explains this (quite counter-intuitive) decision. In short: before Java 5, Properties
implemented Map
(as there were no generics back then). This meant that you could put any Object
in a Properties
object. This is still in the documenation:
这个答案解释了这个(相当反直觉的)决定。简而言之:在Java 5之前,属性实现了Map(那时还没有泛型)。这意味着您可以将任何对象放入属性对象中。这仍在文件中:
Because
Properties
inherits fromHashtable
, theput
andputAll
methods can be applied to aProperties
object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are notString
s. ThesetProperty
method should be used instead.由于属性从Hashtable继承,put和putAll方法可以应用到Properties对象。由于它们允许调用者插入其键或值不是字符串的条目,因此它们的使用非常不理想。应该使用setProperty方法。
To maintain compatibility with this, the designers had no other choice but to make it inherit Map<Object, Object>
in Java 5. It's an unfortunate result of the strive for full backwards compatibility which makes new code unnecessarily convoluted.
为了保持与此的兼容性,设计人员没有其他选择,只能让它继承Map
If you only ever use string properties in your Properties
object, you should be able to get away with an unchecked cast in your constructor:
如果您只在属性对象中使用字符串属性,那么您应该能够在构造函数中不受约束地进行转换:
Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);
or without any copies:
或没有任何副本:
Map<String, String> map = (Map<String, String>) properties;
#9
4
I would use following Guava API: com.google.common.collect.Maps#fromProperties
我将使用以下的番石榴API: com.google.common.collect.Maps#fromProperties。
Properties properties = new Properties();
Map<String, String> map = Maps.fromProperties(properties);
#10
1
this is only because the constructor of HashMap requires an arg of Map generic type and Properties implements Map.
这仅仅是因为HashMap的构造函数需要一个Map泛型类型和属性实现映射的arg。
This will work, though with a warning
这将起作用,尽管有警告。
Properties properties = new Properties();
Map<String, String> map = new HashMap(properties);
#11
0
First thing,
第一件事,
Properties class is based on Hashtable and not Hashmap. Properties class basically extends Hashtable
属性类基于Hashtable而不是Hashmap。属性类基本上扩展了Hashtable。
There is no such constructor in HashMap class which takes a properties object and return you a hashmap object. So what you are doing is NOT correct. You should be able to cast the object of properties to hashtable reference.
HashMap类中没有这样的构造函数,它获取一个属性对象并返回一个HashMap对象。所以你所做的是不正确的。您应该能够将属性的对象转换为hashtable引用。
#1
68
This is because Properties
extends Hashtable<Object, Object>
(which, in turn, implements Map<Object, Object>
). You attempt to feed that into a Map<String, String>
. It is therefore incompatible.
这是因为属性扩展了Hashtable
You need to feed string properties one by one into your map...
您需要将字符串属性逐一输入到您的映射中……
For instance:
例如:
for (final String name: properties.stringPropertyNames())
map.put(name, properties.getProperty(name));
#2
31
The efficient way to do that is just to cast to a generic Map as follows:
这样做的有效方法是将其转换为一个泛型映射,如下所示:
Properties props = new Properties();
Map<String, String> map = (Map)props;
This will convert a Map<Object, Object>
to a raw Map, which is "ok" for the compiler (only warning). Once we have a raw Map
it will cast to Map<String, String>
which it also will be "ok" (another warning). You can ignore them with annotation @SuppressWarnings({ "unchecked", "rawtypes" })
这将把Map
This will work because in the JVM the object doesn't really have a generic type. Generic types are just a trick that verifies things at compile time.
这将起作用,因为在JVM中对象并没有真正的泛型类型。泛型类型只是在编译时验证事物的一个技巧。
If some key or value is not a String it will produce a ClassCastException
error. With current Properties
implementation this is very unlikely to happen, as long as you don't use the mutable call methods from the super Hashtable<Object,Object>
of Properties
.
如果某个键或值不是字符串,它将产生ClassCastException错误。对于当前的属性实现,这是不可能发生的,只要您不使用超级Hashtable
So, if don't do nasty things with your Properties instance this is the way to go.
所以,如果你的属性实例不做龌龊的事情,这就是方法。
#3
25
How about this?
这个怎么样?
Map properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);
Will cause a warning, but works without iterations.
会引起警告,但不会迭代。
#4
20
You could use Google Guava's:
你可以用谷歌番石榴
com.google.common.collect.Maps.fromProperties(Properties)
com.google.common.collect.Maps.fromProperties(属性)
#5
14
Properties
implements Map<Object, Object>
- not Map<String, String>
.
属性实现Map
You're trying to call this constructor:
你要调用这个构造函数
public HashMap(Map<? extends K,? extends V> m)
... with K
and V
both as String
.
…K和V都是字符串。
But Map<Object, Object>
isn't a Map<? extends String, ? extends String>
... it can contain non-string keys and values.
但是Map
This would work:
这将工作:
Map<Object, Object> map = new HashMap<Object, Object>();
... but it wouldn't be as useful to you.
…但它对你没用。
Fundamentally, Properties
should never have been made a subclass of HashTable
... that's the problem. Since v1, it's always been able to store non-String keys and values, despite that being against the intention. If composition had been used instead, the API could have only worked with string keys/values, and all would have been well.
从根本上说,属性不应该被创建为HashTable的子类……这就是问题所在。自v1以来,它总是能够存储非字符串键和值,尽管这违背了意图。如果使用组合,那么API只能使用字符串键/值,而且所有的都很好。
You may want something like this:
你可能想要这样的东西:
Map<String, String> map = new HashMap<String, String>();
for (String key : properties.stringPropertyNames()) {
map.put(key, properties.getProperty(key));
}
#6
13
The Java 8 way:
Java 8道:
properties.entrySet().stream().collect(
Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue().toString()
)
);
#7
4
If you know that your Properties
object only contains <String, String>
entries, you can resort to a raw type:
如果您知道您的属性对象仅包含
Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>((Map) properties);
#8
4
The problem is that Properties
implements Map<Object, Object>
, whereas the HashMap
constructor expects a Map<? extends String, ? extends String>
.
问题是属性实现了Map
This answer explains this (quite counter-intuitive) decision. In short: before Java 5, Properties
implemented Map
(as there were no generics back then). This meant that you could put any Object
in a Properties
object. This is still in the documenation:
这个答案解释了这个(相当反直觉的)决定。简而言之:在Java 5之前,属性实现了Map(那时还没有泛型)。这意味着您可以将任何对象放入属性对象中。这仍在文件中:
Because
Properties
inherits fromHashtable
, theput
andputAll
methods can be applied to aProperties
object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are notString
s. ThesetProperty
method should be used instead.由于属性从Hashtable继承,put和putAll方法可以应用到Properties对象。由于它们允许调用者插入其键或值不是字符串的条目,因此它们的使用非常不理想。应该使用setProperty方法。
To maintain compatibility with this, the designers had no other choice but to make it inherit Map<Object, Object>
in Java 5. It's an unfortunate result of the strive for full backwards compatibility which makes new code unnecessarily convoluted.
为了保持与此的兼容性,设计人员没有其他选择,只能让它继承Map
If you only ever use string properties in your Properties
object, you should be able to get away with an unchecked cast in your constructor:
如果您只在属性对象中使用字符串属性,那么您应该能够在构造函数中不受约束地进行转换:
Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);
or without any copies:
或没有任何副本:
Map<String, String> map = (Map<String, String>) properties;
#9
4
I would use following Guava API: com.google.common.collect.Maps#fromProperties
我将使用以下的番石榴API: com.google.common.collect.Maps#fromProperties。
Properties properties = new Properties();
Map<String, String> map = Maps.fromProperties(properties);
#10
1
this is only because the constructor of HashMap requires an arg of Map generic type and Properties implements Map.
这仅仅是因为HashMap的构造函数需要一个Map泛型类型和属性实现映射的arg。
This will work, though with a warning
这将起作用,尽管有警告。
Properties properties = new Properties();
Map<String, String> map = new HashMap(properties);
#11
0
First thing,
第一件事,
Properties class is based on Hashtable and not Hashmap. Properties class basically extends Hashtable
属性类基于Hashtable而不是Hashmap。属性类基本上扩展了Hashtable。
There is no such constructor in HashMap class which takes a properties object and return you a hashmap object. So what you are doing is NOT correct. You should be able to cast the object of properties to hashtable reference.
HashMap类中没有这样的构造函数,它获取一个属性对象并返回一个HashMap对象。所以你所做的是不正确的。您应该能够将属性的对象转换为hashtable引用。