103 votes

Conversion de java.util.Properties en HashMap<String,String>

Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?

java.util.Properties est une mise en œuvre de java.util.Map Et java.util.HashMap du constructeur reçoit un Map type param. Alors, pourquoi faut-il le convertir explicitement ?

18voto

Jon Skeet Points 692016

Properties met en œuvre Map<Object, Object> - pas Map<String, String> .

Tu essaies d'appeler ce constructeur :

public HashMap(Map<? extends K,? extends V> m)

... avec K y V en tant que String .

Mais Map<Object, Object> n'est pas un Map<? extends String, ? extends String> ... il peut contenir des clés et des valeurs autres que des chaînes de caractères.

Cela pourrait fonctionner :

Map<Object, Object> map = new HashMap<Object, Object>();

... mais ça ne serait pas aussi utile pour vous.

Fondamentalement, Properties n'aurait jamais dû devenir une sous-classe de HashTable ... c'est là le problème. Depuis la version 1, il a toujours été possible de stocker des clés et des valeurs autres que des chaînes de caractères, bien que cela soit contraire à l'intention. Si la composition avait été utilisée à la place, l'API aurait pu uniquement fonctionnait avec des clés/valeurs de chaînes, et tout aurait été parfait.

Vous pourriez vouloir quelque chose comme ça :

Map<String, String> map = new HashMap<String, String>();
for (String key : properties.stringPropertyNames()) {
    map.put(key, properties.getProperty(key));
}

10voto

vatsal mevada Points 1334

J'utiliserais l'API Guava suivante : com.google.common.collect.Maps#fromProperties

Properties properties = new Properties();
Map<String, String> map = Maps.fromProperties(properties);

8voto

Lukas Eder Points 48046

Si vous connaître que votre Properties ne contient que <String, String> vous pouvez recourir à un type brut :

Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>((Map) properties);

5voto

Mattias Buelens Points 7690

Le problème est que Properties met en œuvre Map<Object, Object> alors que le HashMap attend un Map<? extends String, ? extends String> .

Cette réponse explique cette décision (assez contre-intuitive). En bref : avant Java 5, Properties mis en œuvre Map (car il n'y avait pas de génériques à l'époque). Cela signifie que vous pouviez mettre tout Object en un Properties objet. Ceci est encore dans la documentation :

Parce que Properties hérite de Hashtable le put y putAll méthodes peuvent être appliquées à un Properties objet. Leur utilisation est fortement déconseillé car ils permettent à l'appelant d'insérer des entrées dont les clés ou les valeurs ne sont pas String s. Le site setProperty doit être utilisée à la place.

Pour maintenir la compatibilité avec ce dernier, les concepteurs n'ont pas eu d'autre choix que de le faire hériter de Map<Object, Object> en Java 5. C'est un résultat malheureux de l'effort de rétrocompatibilité totale qui rend le nouveau code inutilement compliqué.

Si vous n'utilisez que des propriétés de type chaîne dans votre Properties objet, vous devrait être capable de s'en sortir avec un cast non vérifié dans votre constructeur :

Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);

ou sans aucune copie :

Map<String, String> map = (Map<String, String>) properties;

2voto

Evgeniy Dorofeev Points 52031

C'est seulement parce que le constructeur de HashMap nécessite une arg 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);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X