0Pricing
Java Academy · Lezione

Regole dell'overloading dei metodi

Comprenda come Java risolva i metodi sovraccaricati e quali siano i più comuni problemi di ambiguità.

Regole dell'overloading dei metodi è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Regole dell'overloading dei metodi

L'overloading dei metodi consente di definire più metodi con lo stesso nome ma liste di parametri diverse. Java seleziona la corrispondenza migliore in fase di compilazione applicando regole precise di risoluzione.

Che cos'è l'overloading

I metodi overloaded condividono un nome, ma differiscono per numero, tipo o ordine dei parametri. Il solo tipo restituito NON è sufficiente per eseguire l'overloading.

class Calculator {
    int add(int a, int b)     { return a + b; }
    double add(double a, double b) { return a + b; }
    int add(int a, int b, int c)   { return a + b + c; }

    // compile error — same signature, different return type only:
    // long add(int a, int b) { return a + b; }
}

Calculator calc = new Calculator();
System.out.println(calc.add(1, 2));       // 3 (int)
System.out.println(calc.add(1.5, 2.5));   // 4.0 (double)
System.out.println(calc.add(1, 2, 3));    // 6 (3-arg)

Risoluzione: la corrispondenza più specifica

Java sceglie il metodo applicabile più specifico. Widening, autoboxing e varargs vengono provati in quest'ordine di preferenza.

static void print(int x)    { System.out.println("int: "    + x); }
static void print(long x)   { System.out.println("long: "   + x); }
static void print(Object x) { System.out.println("Object: " + x); }

print(42);       // int: 42 (exact match — most specific)
print(42L);      // long: 42 (exact match)
print(3.14);     // Object: 3.14 (no float match, widening then autoboxing)

Widening prima dell'autoboxing

Java preferisce il widening di un tipo primitivo al suo autoboxing in un wrapper. Questo può produrre risultati sorprendenti.

static void display(long n)    { System.out.println("long: " + n); }
static void display(Integer n) { System.out.println("Integer: " + n); }

int x = 100;
display(x); // long: 100 — widens int to long BEFORE autoboxing to Integer
// This surprises many developers!

static void show(Long n)    { System.out.println("Long"); }
static void show(Integer n) { System.out.println("Integer"); }

// show(100); // compile error — ambiguous! Neither is more specific

Ambiguità degli argomenti null

Passare null a metodi overloaded può creare ambiguità se più metodi accettano tipi reference. Esegua il cast di null per risolvere l'ambiguità.

static void handle(String s)  { System.out.println("String: " + s); }
static void handle(Integer i) { System.out.println("Integer: " + i); }
static void handle(Object o)  { System.out.println("Object"); }

handle((String) null);  // String: null (cast resolves ambiguity)
handle((Integer) null); // Integer: null
// handle(null);        // compile error: ambiguous (String vs Integer)

Overloading con l'ereditarietà

La risoluzione dei metodi considera il tipo dichiarato della variabile di riferimento, non il tipo a runtime: si tratta di una decisione presa in fase di compilazione.

class Animal {}
class Dog extends Animal {}

static void greet(Animal a) { System.out.println("Animal"); }
static void greet(Dog d)    { System.out.println("Dog"); }

Animal a = new Dog(); // declared as Animal
greet(a);   // Animal — compile-time type is Animal!

Dog d = new Dog();
greet(d);   // Dog — compile-time type is Dog

Overloading rispetto a overriding

L'overloading è una decisione presa in fase di compilazione (dispatch statico). L'overriding è una decisione presa a runtime (dispatch dinamico) basata sul tipo effettivo dell'oggetto.

class Base {
    void run() { System.out.println("Base.run"); }
}
class Sub extends Base {
    @Override
    void run() { System.out.println("Sub.run"); } // overriding

    void run(int speed) { System.out.println("Sub.run(" + speed + ")"); } // overloading
}

Base b = new Sub();
b.run();     // Sub.run — override (runtime dispatch)
// b.run(10); // compile error — Base doesn't have run(int)

Pattern comuni di overloading

Usi comuni dell'overloading nelle API: fornire metodi di praticità che delegano a una versione con tutti i parametri.

class Connection {
    void connect(String host, int port, int timeout) {
        System.out.println("Connecting to " + host + ":" + port + " timeout=" + timeout);
    }

    // Convenience overloads
    void connect(String host, int port) {
        connect(host, port, 30); // delegate with default timeout
    }

    void connect(String host) {
        connect(host, 5432); // delegate with default port
    }
}

new Connection().connect("db.example.com");
// Connecting to db.example.com:5432 timeout=30

Overloading e generics

L'overloading dei metodi generici richiede attenzione: la type erasure può rendere identiche, dopo la compilazione, due firme apparentemente diverse.

// Type erasure problem: both methods erase to the same signature!
// static void process(List<String> list) {} // compile error
// static void process(List<Integer> list) {} // duplicate after erasure

// Solutions:
// 1. Use different method names: processStrings / processIntegers
// 2. Use a generic method with bounded type:
static <T extends Number> void processNumbers(List<T> list) {
    list.forEach(n -> System.out.println(n.doubleValue()));
}
processNumbers(List.of(1, 2, 3));
processNumbers(List.of(1.5, 2.5));

Pratica: overload in stile builder

L'overloading è comune nelle API builder e factory per offrire una creazione flessibile degli oggetti.

class Notification {
    final String title, body;
    final String imageUrl;
    final boolean urgent;

    // Factory overloads for convenience
    static Notification simple(String title, String body) {
        return new Notification(title, body, null, false);
    }
    static Notification urgent(String title, String body) {
        return new Notification(title, body, null, true);
    }
    static Notification withImage(String title, String body, String url) {
        return new Notification(title, body, url, false);
    }
    Notification(String title, String body, String imageUrl, boolean urgent) {
        this.title = title; this.body = body;
        this.imageUrl = imageUrl; this.urgent = urgent;
    }
}

Problemi comuni dell'overloading

Eviti questi errori comuni nell'overloading:

  • Troppi overload per la stessa operazione: utilizzi invece un builder
  • Overload che differiscono solo per l'ordine dei parametri: possono creare confusione
  • Widening inaspettato: un int può essere risolto come long invece che come Integer
// Confusing: order-based overloads
// void save(String name, int age)  {}
// void save(int age, String name)  {} // very confusing!

// Better: use a record/DTO
record UserData(String name, int age) {}
void save(UserData data) {}

// Surprising widening
static void m(long x)   { System.out.println("long"); }
static void m(Integer x){ System.out.println("Integer"); }
int v = 5;
m(v); // long! widening preferred over autoboxing

Verifica rapida

Se un metodo è sovraccaricato con parametri di tipo long e Integer, quale viene scelto quando si passa un argomento int?

Riepilogo: regole del sovraccarico dei metodi

Punti chiave:

  • Il sovraccarico differisce per numero, tipo o ordine dei parametri, NON per il solo tipo restituito
  • Java risolve i sovraccarichi in fase di compilazione usando il tipo dichiarato degli argomenti
  • L'allargamento di un tipo primitivo è preferito alla conversione automatica in un wrapper
  • Gli argomenti null possono causare ambiguità: utilizzi un cast per risolverla: handle((String) null)
  • Il sovraccarico avviene in fase di compilazione, l'override in fase di esecuzione: sono meccanismi diversi
  • Utilizzi sovraccarichi di comodità che delegano a un metodo principale con tutti i parametri

Domande Frequenti

La lezione «Regole dell'overloading dei metodi» è gratuita?

Sì — il testo completo di «Regole dell'overloading dei metodi» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Regole dell'overloading dei metodi»?

Comprenda come Java risolva i metodi sovraccaricati e quali siano i più comuni problemi di ambiguità. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Regole dell'overloading dei metodi»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Regole dell'overloading dei metodi
  2. Parametri varargs
  3. Campi statici e costanti
  4. Classi di utilità e metodi factory statici
← Torna a Java Academy