Votre 1st cas est assez simple. La méthode ci-dessous:
public MyContainer<IntWrapper> pack(int key, Object[] values)
est une correspondance exacte pour les arguments - (1, String[])
. De JLS Section 15.12.2:
La première phase (§15.12.2.2) effectue la résolution de surcharge, sans permettre de boxe ou unboxing de conversion
Maintenant, il n'est pas de la boxe, en passant les paramètres pour la 2ème méthode. En tant que Object[]
est un super type d' String[]
. Et en passant String[]
argument pour Object[]
paramètre est valide invocation avant même de Java 5.
Compilateur semble jouer un tour dans votre 2e cas:
Dans le 2ème cas, puisque vous avez utilisé var-args, la surcharge de la méthode de résolution sera fait en utilisant les deux var-args, et de la boxe ou unboxing, comme pour la 3ème phase expliqué dans ce JLS section:
La troisième phase (§15.12.2.4) permet de surcharger être combinée avec une variable d'arité de méthodes, de boxe, et unboxing.
Remarque, la phase 2 n'est pas applicable ici, en raison de l'utilisation de var-args:
La deuxième phase (§15.12.2.3) effectue la résolution de surcharge, tout en permettant boxing et unboxing, mais encore s'oppose à l'utilisation de la variable d'arité de l'invocation de méthode.
Maintenant ce qui se passe ici est le compilateur n'est pas inférer le type d'argument correctement* (en Fait, c'est inférer correctement le type de paramètre est utilisé comme paramètre formel, voir la mise à jour vers la fin de cette réponse). Donc, pour votre invocation de méthode:
MyContainer<IntWrapper> test = converter.pack(1, "Test", "Test2");
compilateur doit avoir déduit le type d' K
au générique de la méthode de IntWrapper
, à partir de la LHS. Mais il semble que c'est l'inférence K
un Integer
type, en raison de laquelle les deux méthodes sont désormais également applicable pour l'appel de cette méthode, à la fois comme l'exige var-args
ou boxing
.
Toutefois, si le résultat de cette méthode n'est pas attribué à certains de référence, alors je peux comprendre que le compilateur ne peut pas en déduire un type approprié, car dans ce cas, où est-il est parfaitement acceptable de donner à une erreur d'ambiguïté:
converter.pack(1, "Test", "Test2");
Peut-être que je pense, pour maintenir la cohérence, c'est aussi marqué ambigu pour le premier cas. Mais, encore une fois je ne suis pas vraiment sûr, que je n'ai pas trouvé de source crédible de JLS, ou d'un autre fonctionnaire de référence qui parle de ce problème. Je vais continuer à chercher, et si j'arrive à en trouver un, permettra de mettre à jour la réponse.
Nous allons truc le compilateur par type explicite de l'information:
Si vous modifiez l'invocation de la méthode pour donner explicite des informations de type:
MyContainer<IntWrapper> test = converter.<IntWrapper>pack(1, "Test", "Test2");
Maintenant, le type K
sera déduit qu' IntWrapper
, mais depuis 1
n'est pas convertible en IntWrapper
, cette méthode est abandonnée, et le 2e de la méthode invoke et il fonctionne parfaitement bien.
Franchement, je ne sais vraiment pas ce qui se passe ici. Je m'attends à ce que le compilateur de déduire le type de paramètre à partir de l'invocation de la méthode du contexte dans le premier cas également, comme il travaille pour le problème suivant:
public static <T> HashSet<T> create(int size) {
return new HashSet<T>(size);
}
// Type inferred as `Integer`, from LHS.
HashSet<Integer> hi = create(10);
Mais, il n'est pas en train de faire dans ce cas. Donc cela peut éventuellement être un bug.
*Ou peut-être que je ne comprends pas exactement comment le Compilateur déduit le type des arguments, quand le type n'est pas passée en argument. Donc, pour en apprendre plus à ce sujet, j'ai essayé de passer par - JLS §15.12.2.7 et JLS §15.12.2.8, qui est sur la façon dont le compilateur déduit le type de l'argument, mais qui va complètement sur le très haut de ma tête.
Donc, pour l'instant, vous avez à vivre avec elle, et utiliser l'autre (fourniture de type explicite argument).
Il s'avère que le Compilateur n'a pas jouer à n'importe quel truc:
Comme enfin expliqué dans le commentaire de @zhong.j.yu., compilateur ne s'applique section 15.12.2.8 pour l'inférence de type, quand il ne parvient pas à déduire comme par 15.12.2.7 section. Mais ici, il est possible de déduire le type Integer
de l'argument étant passé, comme l'indique clairement le type de paramètre est un paramètre format de la méthode.
Donc, oui compilateur correctement déduit le type Integer
, et d'où l'ambiguïté est valide. Et maintenant, je pense que cette réponse est complète.