Java sovraccarico regole

Mi sono imbattuto in due il sovraccarico di domande recente che non riesco a trovare una risposta e non hai un ambiente java per eseguire alcuni test di codice. Sto sperando che qualcuno mi possa aiutare, assemblando un elenco di tutte le regole che java compilatori attenersi per il sovraccarico o, in alternativa, indicando me in un elenco che già esiste.

Prima, quando i due metodi differiscono solo per un finale varargs parametro, in quali circostanze e a fare di ogni chiamata e si può chiamare il varargs metodo senza alcuna args?

private void f(int a) { /* ... */ }
private void f(int a, int... b) { /* ... */ }

f(12); //calls the former? I would expect it to
f(12, (int[])null); //calls latter, but passes null for b? 
  //Can I force the compiler to call the second method in the same fashion
  //as would happen if the first method didn't exist?

Seconda domanda, quando due metodi diversi tipi ereditato da un altro che viene chiamato? Mi sarei aspettato più versione derivata di essere chiamato, e la colata di permesso di chiamare gli altri.

interface A {}
class B implements A {}
class C implements A {}

private void f(A a) {}
private void f(B b) {}

f(new C()); //calls the first method
f(new B()); //calls the second method?
f((A)(new B()); //calls the first method using a B object?

Questi sono due esempi, ma come un codice-reader io preferirei una lista canonica dell’esatto ordinato di regole utilizzate per la risoluzione di questo, come mi capita spesso di non avere il tempo di installazione di un ambiente di compilazione, per verificare ciò che il compilatore fa.

OriginaleL’autore Peter Oehlert | 2012-06-05

2 risposte

  1. 19

    Sovraccarico vs Override

    La selezione dei diritto attuazione metodo è di fatto in fase di runtime, come ben sottolineato, ora la firma del metodo da invocare è deciso in fase di compilazione.

    Overloading del Metodo di Selezione in fase di Compilazione

    Il Specifica Del Linguaggio Java (JLS) nella sezione 15.12 Invocazione Di Metodo Espressioni spiega in dettaglio il processo che il compilatore segue per scegliere il giusto metodo da richiamare.

    C’, si noterà che questo è un in fase di compilazione attività. I JLS dice nella sottosezione 15.12.2:

    Questo passo utilizza il nome del metodo e i tipi di argomento espressioni
    per individuare metodi sono entrambi accessibili e applicabile
    Ci possono essere più di uno di questi metodi, in questo caso più specifico si è scelto.

    In genere, varargs metodi sono l’ultima scelta, se si trovano a competere con altri candidati metodi, perché sono considerati meno specifici rispetto a quelli che ricevono lo stesso tipo di parametro.

    Per verificare la compilazione natura di questo, è possibile effettuare il seguente test.

    Dichiarare una classe come questa e compilarlo.

    public class ChooseMethod {
       public void doSomething(Number n){
        System.out.println("Number");
       }
    }

    Dichiarare una seconda classe che richiama un metodo del primo e compilarlo.

    public class MethodChooser {
       public static void main(String[] args) {
        ChooseMethod m = new ChooseMethod();
        m.doSomething(10);
       }
    }

    Se si richiama il principale, l’output dice Number.

    Ora, aggiungere un secondo più specifico sovraccarico metodo per la ChooseMethod classe e ricompilarlo (ma non ricompilare l’altra classe).

    public void doSomething(Integer i) {
     System.out.println("Integer");
    }

    Se si esegue il principale, di nuovo, l’uscita è ancora Number.

    Fondamentalmente, perché è stato deciso al momento della compilazione. Se si ricompila il MethodChooser classe (il principale) ed eseguire di nuovo il programma, l’uscita sarà Integer.

    Come tale, se si desidera forzare la selezione di uno dei metodi di overload, il tipo di argomenti devono corrispondere con il tipo di parametri in fase di compilazione, e non solo in fase di esecuzione.

    L’override del Metodo di Selezione in fase di Esecuzione

    Di nuovo, la firma del metodo è deciso in fase di compilazione, ma l’effettiva attuazione è deciso in fase di runtime.

    Dichiarare una classe come questa e compilarlo.

    public class ChooseMethodA {
       public void doSomething(Number n){
        System.out.println("Number A");
       }
    }

    Quindi dichiarare una seconda estensione di classe e compilare:

    public class ChooseMethodB extends ChooseMethodA {  }

    E nel MethodChooser classe:

    public class MethodChooser {
        public static void main(String[] args) {
            ChooseMethodA m = new ChooseMethodB();
            m.doSomething(10);
        }
    }

    E se lo si esegue, si ottiene l’uscita Number A, e questo è Ok, perché il metodo non è stato sottoposto a override in ChooseMethodB e pertanto l’attuazione di essere invocato è quello di ChooseMethodA.

    Ora, aggiungere un sovrascritto il metodo in MethodChooserB:

    public void doSomething(Number n){
        System.out.println("Number B");
    }

    E ricompilare solo questo, e di eseguire il metodo principale di nuovo.

    Ora, si ottiene l’uscita Number B

    Come tale, l’implementazione è stato scelto in fase di runtime, e non la ricompilazione del MethodChooser classe è stato richiesto.

    Veramente la domanda, vorrei avere risposto è quello che determina la “più specifico”. C’è un elenco numerato che può essere fatto per determinare quale verrà chiamata la funzione.
    Hai letto il link che ho condiviso da JLS? Se non si trova una risposta non troverete altrove.
    L’ho fatto dopo che ho fatto il commento. Che è il riferimento definitivo su ciò che il compilatore dovrebbe fare in modo che sia veramente il link che stavo cercando. Certamente non è il più facile leggere, e io probabilmente provare a prendere una pugnalata a venire con un più pratico distillazione di esso come qualcosa di diverso non sembra esistere.
    Certo ci vuole del tempo per digerire, a causa del linguaggio formale utilizzato nelle spiegazioni. Certo, se ti siedi e provare un paio di righe di codice, e con un po ‘di pazienza, un po’ di tempo si potrebbe venire con un buon compendio di esempi che vale la pena condividere. Penso che mi piacerebbe vedere e che varrebbe la pena di un post in qualsiasi blog o qui, come una risposta alla tua domanda.
    Secondo grassetto il titolo dovrebbe essere l’Overload del Metodo di Selezione in fase di Compilazione.

    OriginaleL’autore Edwin Dalorzo

  2. 1

    Prima domanda:

    La tua ipotesi è corretta. La seconda chiamata a f() chiamerà il varargs metodo. È possibile ottenere il compilatore di chiamare il secondo metodo:

    private void f(int a) {
        f(a, null);
    }

    Seconda domanda:

    Sì. Tuttavia, non è possibile estendere un’interfaccia. Se si modifica A a una classe astratta, le cose compilare.

    Si potrebbe sempre provare f(a, new int[0]);

    OriginaleL’autore gobernador

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *