2010-06-09 17 views
4

Je veux faire une carte-type de conteneur qui a l'interface suivante:cartographie typées de la classe <T> Thing <T>

public <T> Thing<T> get(Class<T> clazz); 
public <T> void put(Class<T> clazz, Thing<T> thing); 

Le point intéressant est que les T s dans chaque Class<T> ->Thing<T> La paire est la même T, mais le conteneur doit pouvoir contenir plusieurs types de paires différents. Initialement, j'ai essayé un (Hash) Map. Mais, par exemple,

Map<Class<T>, Thing<T>> 

est pas juste, car alors T serait le même T pour toutes paires dans cette carte. Bien sûr,

Map<Class<?>, Thing<?>> 

fonctionne, mais je ne disposent pas de garanties de type sécurité de telle sorte que quand je get(String.class), je ne peux pas être sûr que je reçois une instance Thing<String> arrière.

Existe-t-il un moyen évident de réaliser le type de sécurité que je recherche?

Répondre

5

La carte elle-même ne le garantirait pas, mais si vous n'y accédez que par les méthodes ci-dessus, vous aurez la sécurité désirée.

+0

J'ai essayé cela (un interne 'Map , Thing >', la méthode put fonctionne bien, mais la méthode ne compile pas, elle dit "incompatibles types, trouvé: Thing ; " –

+0

Cela dit, l'ajout d'un cast' (Thing ) 'l'a corrigé Bien que ce soit en principe un cast non contrôlé, vous avez raison de dire qu'il réussira toujours si j'accède à la carte uniquement via les méthodes sécurisées. –

+2

@Joonas: C'est comme ça que vous faites des astuces de type avancé, faites quelque chose que le compilateur pense être un peu dangereux et qui est en fait OK parce que vous faites les garanties de sécurité à un niveau plus élevé. ")' pour empêcher le compilateur de gémir à ce sujet –

2

Si vous voulez pouvoir mettre différents types ne devriez-vous pas déclarer deux types de paramètres?

public <K, V> Thing<V> get(Class<K> clazz); 
public <K, V> void put(Class<K> clazz, Thing<V> thing); 

ou ai-je mal compris la question? Editer: Je vois bien, si vous voulez o conteneur qui peut contenir des entités de types différents, vous ne pouvez pas avoir la sécurité complète du type, puisque lorsque vous déclarez votre conteneur, vous pouvez seulement mettre un type sur le conteneur, puis vous pouvez être en mesure de mettre des objets, mais vous ne pouvez pas être sûr de ce que vous obtenez. Au mieux, vous finirez par mettre des objets en tant qu'Objet, puis en faisant instanceof et en jetant quand vous les récupérerez. Toutes les collections ont ce problème. Imaginez que vous avez un Collection<T extends Thing>. Vous pouvez y mettre Things, ChildOfThings, ou GrandChildOfThings, mais quand vous le récupérez, vous êtes seulement garanti que c'est une chose, vous ne pouvez pas dire si c'est un enfant ou GrandChild, sans le tester.

+0

Je voulais dire que le 'T' est le même pour la clé et valeur dans une paire clé-valeur spécifique, mais varie d'une paire clé-valeur à l'autre. –