8
votes

Comment le type générique est-il inféré ici?

public static void main(String[] args) {
    Map<String, Map<Long, List<String>>> map = getHashMap();
}

static <K,V> Map<K,V> getHashMap()
{
    return new HashMap<K, V>();
}
I saw a similar code in google guava (as factory methods) for making instances of Hashmap without mentioning the generic types.I don't understand how the generic is getting inferred by the above program.I mean how can the function getHashMap understand the type of map since i'm not passing any type information to the function.  

0 commentaires

3 Réponses :


6
votes

La fonction gethashmap n'a pas à déduire les types. C'est sur le site d'appel que Javac est requis par la spécification de langue Java pour déduire que les types d'accord ( 15.12.2.7 Arguments de type infesser sur des arguments réels ).

Je pense que le plan actuel est (toujours) pour JDK7 pour soutenir l'opérateur de diamants , donc ce type de chose fonctionnera avec nouveau aussi, bien que avec un peu de syntaxe apparemment inutile. xxx


5 commentaires

Pouvez-vous expliquer un peu.


@Tom: Que voulez-vous dire que Javac déduira le type.can que vous expliquez comment cette chose fonctionne en étapes.


@Emil La spécification réelle est compliquée. Voir le lien. Généralement, cela fait ce que vous voulez la plupart du temps.


Petite question: Depuis qu'enregistrer, il n'y a pas de différence entre hashmap et une vieille hashmap uni, car l'effacement de type fait de toutes les haussures de la même manière, avons-nous vraiment une inférence de type ou c'est plus comme "Tapez l'indifférence"? Je veux dire, l'objet c'est juste un hashmap. La variable a les informations , mais uniquement dans le temps de compilation


@Pablo Eh bien, il peut attraper des erreurs. Par exemple, si la mise en œuvre de la mappe particulière impliquée a nécessité un sous-type de clés . Je pense que l'implémentation Javac est d'attribuer un marqueur aux types de la méthode et de voir où ils sont attribués, plutôt que de commencer par la déclaration de variable et de travailler à l'envers à l'invocation de la méthode.



1
votes

au niveau de la bytecode, la méthode aura un descripteur qui vient de dire qu'il y a une méthode avec le nom gethashmap, qui ne prend aucun argument et renvoie une carte (pas de génériques).

alors lorsque le compilateur analyse la ligne Carte >> Carte = gethashamap (); CODE>, et cela dira, ok, je dois avoir une variable avec un type déclaré de Carte >> code>, mais pour obtenir l'instance, je dois appeler une méthode. À ce stade, il s'agit du travail du compilateur de vérifier si le type de retour de la méthode correspond au type déclaré de la variable de votre affectation de ce résultat. Donc il vérifie si chaîne code> correspond à k code> et si mappe > code> correspond à V, ce qu'ils font, ce qu'ils le font que l'affectation est de type sécuritaire et génère le bytecode qui utilise essentiellement une variable de carte (sans génériques). p>

Si vous auriez déclaré votre méthode comme: P>

static <K extends Number,V> Map<K,V> getHashMap()
{
    return new HashMap<K, V>();
}


0 commentaires

1
votes
class XX
  static <T> T foo(){ return new T(); }

String  s = XX.foo();
Integer i = XX.foo();

0 commentaires