7

Perché il seguente programma genera un'eccezione?Domanda SCJP: sovraccarico del metodo Java con var-args. Qual è la logica?

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"); 
    } 

}

Procedimento CallMethod (integer []) è ambiguo per il tipo MainClass

OK, posso vedere che uno dei due metodi funzionerà (se il l'altro è commentato), ma so anche che esiste una gerarchia su ciò che accade se una primitiva non corrisponde esattamente al tipo di input di un metodo.

La prima cosa che si tenta è di allargare il primitivo. Quindi, se ci fosse un terzo metodo:

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

il codice sarebbe stampare lungo

La seconda cosa è di box primitivo. Quindi se c'era un metodo che prendeva un intero, quello sarebbe stato invocato.

La terza priorità è var-args.

In base alla priorità di cui sopra, mi aspetto che sia la seconda priorità. Mi aspetterei che l'int sia racchiuso in un intero e che il (intero ...) venga invocato. Ma ovviamente questo non succede. Invece, viene lanciata l'eccezione.

Qualcuno vede e può spiegare perché la priorità non si applica in questo esempio?

Cheers!

risposta

9

Hai ragione che l'ampliamento viene prima della boxe, che a sua volta viene prima di var-args.

Ma sembra che si tratti il ​​primo metodo come callMethod(Integer i), non callMethod(Integer... i). Poiché entrambi i metodi utilizzano var-args, esiste una priorità legame. Cioè, nessuno dei due soddisfa i criteri per il pugilato da solo, ma entrambi soddisfano i criteri per var-args.

Ricorda che è illegale allargare, quindi boxare (anche se ho fatto qualche ricerca prima di postare questa risposta e ho scoperto che è legale boxare, quindi ampliare). Allo stesso modo, non otterrai la scatola, quindi il comportamento di var-args; il compilatore salta direttamente al passo var-args e vede due metodi che accettano var-args.

EDIT: Vorrei chiarire che si otterrà il comportamento di box-then-var-args se non c'è ambiguità. In altre parole, se ci fosse solo uno callMethod() e ci sia voluto Integer... i, si otterrebbe "Wrapper".

+0

Ho pensato che avrebbe provato i tre approcci e il primo ad essere "invocabile" sarebbe stato invocato. Anche se il metodo prende (Integer ... i), mi aspettavo che la boxe in un Integer avrebbe reso quel metodo "invocabile". Ma, come dici tu, sembra che anche la successiva "var-argization" sia presa in considerazione. Saluti! –

Problemi correlati