7

Pourquoi le programme suivant lance-t-il une exception?Question SCJP: surcharger la méthode Java avec var-args. Quelle est la raison?

public class MainClass{ 
    public static void main(String[] argv){ 
     callMethod(2); 
    } 
    public static void callMethod(Integer... i){ 
     System.out.println("Wrapper"); 
    } 
    public static void callMethod(int... i){ 
     System.out.println("Primitive"); 
    } 

}

La méthode callMethod (entier []) est ambigu pour le type MainClass

OK, je peux voir que l'une des deux méthodes fonctionnera (si le l'autre est commenté), mais je sais aussi qu'il y a une hiérarchie sur ce qui se passe si une primitive n'est pas exactement assortie par le type de l'entrée d'une méthode.

La première chose qui est essayée est d'élargir la primitive. Donc, s'il y avait une troisième méthode:

 public static void callMethod(long i){ 
     System.out.println("long"); 
     } 

Le code imprimerait à long

La deuxième chose est de la boîte primitive. Donc, s'il y avait une méthode qui prenait un entier, ce serait celle invoquée.

La troisième priorité est var-args.

Sur la base de la priorité ci-dessus, je m'attendrais à ce que la deuxième priotité soit le cas. Je m'attendrais à ce que l'int soit enveloppé dans un entier et l'entier (Integer ...) serait invoqué. Mais bien sûr, cela n'arrive pas. Au lieu de cela, l'exception est levée.

Est-ce que quelqu'un voit et peut expliquer pourquoi la priorisation ne s'applique pas dans cet exemple?

À la votre!

Répondre

9

Vous avez raison de dire que l'élargissement précède la boxe, elle-même précédée de var-args. Mais vous semblez traiter la première méthode comme callMethod(Integer i), pas callMethod(Integer... i). Puisque les deux méthodes utilisent var-args, il y a une priorité tie. C'est-à-dire que ni l'un ni l'autre ne remplissent les critères de la boxe seuls, mais tous deux répondent aux critères des var-args. Rappelez-vous qu'il est illégal d'élargir, puis boîte (bien que j'ai fait quelques recherches avant de poster cette réponse et a constaté qu'il est légal de boxer, puis élargir). De même, vous n'obtiendrez pas de boîte, alors le comportement de var-args; le compilateur passe directement à l'étape var-args et voit deux méthodes qui prennent var-args.

EDIT: Je dois préciser que vous obtiendrez le comportement box-then-var-args s'il n'y a pas d'ambiguïté. En d'autres termes, s'il n'y avait qu'un seul callMethod(), et qu'il fallait Integer... i, vous obtiendriez «Wrapper».

+0

Je pensais qu'il essayait les trois approches et que le premier était "invocable". Bien que la méthode prenne (Integer ... i), je m'attendais à ce que boxer dans un Integer rende cette méthode "invocable". Mais, comme vous le dites, il semble que la "var-arg-isation" ultérieure soit également prise en compte. À votre santé! –

Questions connexes