2008-09-01 8 views
9

Existe-t-il un moyen abrégé de définir et d'utiliser des définitions génériques sans avoir à répéter une description générique particulière de sorte que s'il y a un changement je n'ai pas besoin de changer toutes les définitions? est somethhing comme cela possible:Generics in Java

Typedef myGenDef = < Object1, Object2 >; 

HashMap<myGenDef> hm = new HashMap<myGenDef>(); 

for (Entry<myGenDef> ent : hm..entrySet()) 
{ 
. 
. 
. 
} 

Répondre

11

Il y a le pseudo-typedef antipattern ...

class StringList extends ArrayList<String> { } 

Bonnes choses, buvez! ;-)

Comme le note l'article, cette technique a quelques problèmes sérieux, principalement que ce "typedef" est en fait une classe distincte et ne peut donc être utilisé indifféremment avec le type qu'il étend ou d'autres types définis de manière similaire.

+0

Ce n'est peut-être pas une bonne idée d'accepter un antipattern comme solution à votre question, surtout lorsqu'il existe des alternatives. Mais si cela vous a aidé avec votre problème particulier ... –

+0

(Sans tenir compte de l'admonition des modérateurs sur le bruit sur les threads "typedef in Java") ... C'est pire qu'un anti-pattern. Il crée un nouveau type de première classe, avec ses propres entrées dans les tables de méthodes virtuelles, et toutes ces obligations.Un typedef C++ rendrait simplement la partie "ArrayList " DRY, de sorte que vous pouvez changer String (ou ArrayList) en un seul endroit. – Phlip

+0

Oui, les typedefs C/C++ sont une fonctionnalité de langage respectée avec un bon support et beaucoup d'utilisations légitimes. Ce n'est pas. D'où toute la chose "antipattern". – Shog9

1

No. Bien que, groovy, un langage machine virtuelle Java, est typé dynamiquement et vous permettrait d'écrire:

def map = new HashMap<complicated generic expression>(); 
+0

Idem avec Scala. Ces langues offrent une syntaxe qui peut déduire des types à partir d'instructions d'instanciation variables. Ceci est similaire à ce qui est proposé dans .NET avec le mot-clé var. Ne confondez pas cela avec des langages faiblement (ou vaguement) typés qui vous permettent de hasarder un type variable à la volée; la JVM impose toujours une typage fort dans son code compilé. –

4

Dans une méthode générique, vous pouvez utiliser une forme limitée d'inférence de type pour éviter certaines répétitions.

Exemple: si vous avez la fonction

<K, V> Map<K, V> getSomething() { 
     //... 
    } 

vous pouvez utiliser:

final Map<String, Object> something = getsomething(); 

au lieu de:

final Map<String, Object> something = this.<String, Object>getsomething(); 
3

Utilisation Factory Pattern pour la création de Génériques:

Méthode Exemple:

public Map<String, Integer> createGenMap(){ 
     return new HashMap<String,Integer>(); 

    } 
2

Le pseudo-antimodèle typedef mentionné par Shog9 fonctionnerait - mais il est recommandé de ne pas utiliser un anti - mais il ne répond pas à vos intentions. L'objectif du pseudo-typedef est de réduire le fouillis dans la déclaration et d'améliorer la lisibilité.

Ce que vous voulez, c'est pouvoir remplacer un groupe de déclarations génériques par un seul métier. Je pense que vous devez vous arrêter et penser: "de façon sorcière est-ce utile?". Je veux dire, je ne peux pas penser à un scénario où vous auriez besoin de cela. Imaginez la classe A:

class A { 
    private Map<String, Integer> values = new HashMap<String, Integer>(); 
} 

Imaginez maintenant que je veux changer le champ 'values' en Map. Pourquoi existe-t-il de nombreux autres champs dispersés dans le code qui nécessite le même changement? En ce qui concerne les opérations qui utilisent des «valeurs», un simple refactoring serait suffisant.