Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?
java.util.Properties
est une implémentation de java.util.Map
, java.util.HashMap
le constructeur de And reçoit un Map
paramètre de type. Alors, pourquoi doit-il être converti explicitement?
Hashtable<Object, Object>
, même des choses qui ne sont pas des chaînes - même des clés qui ne sont pas des chaînes.Le moyen efficace de le faire est simplement de convertir en une carte générique comme suit:
Properties props = new Properties(); Map<String, String> map = (Map)props;
Cela convertira a
Map<Object, Object>
en une map brute, ce qui est "ok" pour le compilateur (seul avertissement). Une fois que nous avons un raw,Map
il sera casté dansMap<String, String>
lequel il sera également "ok" (un autre avertissement). Vous pouvez les ignorer avec une annotation@SuppressWarnings({ "unchecked", "rawtypes" })
Cela fonctionnera car dans la JVM, l'objet n'a pas vraiment de type générique. Les types génériques ne sont qu'une astuce qui vérifie les choses au moment de la compilation.
Si une clé ou une valeur n'est pas une chaîne, cela produira une
ClassCastException
erreur. Avec l'Properties
implémentation actuelle, il est très peu probable que cela se produise, tant que vous n'utilisez pas les méthodes d'appel mutables du superHashtable<Object,Object>
deProperties
.Donc, si vous ne faites pas de mauvaises choses avec votre instance Properties, c'est la voie à suivre.
la source
Map
instance au moins au code donné, alors j'ai pensé que c'était ce dont il avait besoinVous pouvez utiliser Google Guava:
com.google.common.collect.Maps.fromProperties (Propriétés)
la source
Que dis-tu de ça?
Map properties = new Properties(); Map<String, String> map = new HashMap<String, String>(properties);
Provoque un avertissement, mais fonctionne sans itérations.
la source
Map<Object, Object>
, c'est unMap
argument (type brut). Cette réponse est correcte(Map<String, String>) ((Map) properties)
La manière Java 8:
la source
Properties
implémenteMap<Object, Object>
- nonMap<String, String>
.Vous essayez d'appeler ce constructeur:
public HashMap(Map<? extends K,? extends V> m)
... avec
K
et lesV
deux commeString
.Mais
Map<Object, Object>
n'est pas unMap<? extends String, ? extends String>
... il peut contenir des clés et des valeurs sans chaîne.Cela fonctionnerait:
Map<Object, Object> map = new HashMap<Object, Object>();
... mais cela ne vous serait pas aussi utile.
Fondamentalement,
Properties
je n'aurais jamais dû faire une sous-classe deHashTable
... c'est le problème. Depuis la v1, il a toujours été en mesure de stocker des clés et des valeurs non-String, bien que cela soit contraire à l'intention. Si la composition avait été utilisé à la place, l'API aurait pu ne travaillé avec les clés de chaîne / valeurs, et tout aurait été bien.Vous voudrez peut-être quelque chose comme ceci:
Map<String, String> map = new HashMap<String, String>(); for (String key : properties.stringPropertyNames()) { map.put(key, properties.getProperty(key)); }
la source
Properties<String,String> properties = new Properties<String,String>();
. Particulier.Properties
soi n'est pas générique.J'utiliserais l'API Guava suivante: com.google.common.collect.Maps # fromProperties
Properties properties = new Properties(); Map<String, String> map = Maps.fromProperties(properties);
la source
Si vous savez que votre
Properties
objet ne contient que des<String, String>
entrées, vous pouvez recourir à un type brut:Properties properties = new Properties(); Map<String, String> map = new HashMap<String, String>((Map) properties);
la source
Le problème est que
Properties
implémenteMap<Object, Object>
, alors que leHashMap
constructeur attend unMap<? extends String, ? extends String>
.Cette réponse explique cette décision (assez contre-intuitive). En bref: avant Java 5,
Properties
implémentéMap
(car il n'y avait pas de génériques à l'époque). Cela signifie que vous pouvez mettre toutObject
dans unProperties
objet. Ceci est toujours dans la documentation:Pour maintenir la compatibilité avec cela, les concepteurs n'avaient d'autre choix que de le faire hériter
Map<Object, Object>
de Java 5. C'est un résultat malheureux de l'effort de compatibilité descendante totale qui rend le nouveau code inutilement alambiqué.Si vous n'utilisez que des propriétés de chaîne dans votre
Properties
objet, vous devriez pouvoir vous en sortir avec un cast non coché dans votre constructeur:Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);
ou sans aucune copie:
la source
public HashMap(Map<? extends K, ? extends V> m)
. Il ne s'attend pas à unMap<String, String>
Map<Object, Object>
vrai : a ne peut pas être utilisé pour un argument formel de type` Map <? étend String,? étend la chaîne> `.c'est uniquement parce que le constructeur de HashMap nécessite un argument de type générique Map et que Properties implémente Map.
Cela fonctionnera, mais avec un avertissement
Properties properties = new Properties(); Map<String, String> map = new HashMap(properties);
la source
Vous pouvez utiliser ceci:
Map<String, String> map = new HashMap<>(); props.forEach((key, value) -> map.put(key.toString(), value.toString()));
la source
Première chose,
Il n'y a pas de constructeur de ce type dans la classe HashMap qui prend un objet properties et vous renvoie un objet hashmap. Donc ce que vous faites n'est PAS correct. Vous devriez pouvoir convertir l'objet de propriétés en référence de table de hachage.
la source
j'utilise ceci:
for (Map.Entry<Object, Object> entry:properties.entrySet()) { map.put((String) entry.getKey(), (String) entry.getValue()); }
la source