"Ciao, Amigo! Un paio di giorni fa ti ho parlato dei metodi di sovraccarico. Hai capito tutto?"

"Sì. Ricordo. Ogni metodo di classe deve essere unico. Un metodo membro è unico se la classe non ha altri metodi con lo stesso nome e tipo di parametro (e l'ordine dei parametri è importante)."

"Molto bene! Vedo che hai imparato bene quella lezione. Oggi voglio ampliare un po' le tue conoscenze su questo argomento. Quale metodo pensi che verrà chiamato in ogni caso?"

Codice
class Cat
{
 public static void print(int n)
 {
  System.out.println(n);
 }
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }
public static void main(String[] args)
{
  Cat.print(1);
  Cat.print((byte)1);
  Cat.print("1");
  Cat.print(null);
 }
}

"È difficile da dire."

"Nel primo caso, 1 è un int . Abbiamo una corrispondenza del 100% con il metodo che accetta un int. Verrà chiamato il primo void print(int n) .

Nel secondo caso, non abbiamo un metodo che prenda un byte. Ma ci sono due metodi che accettano short e int. In base alle regole di ampliamento del tipo, un byte verrà prima ampliato a short e quindi ampliato a int. Pertanto, il verdetto è che void print(short n). verrà chiamato.

Nel terzo caso, abbiamo una corrispondenza del 100% con il metodo che accetta una stringa. Il vuoto print(String s). verrà chiamato il metodo.

Il quarto caso è ambiguo. null non ha un tipo specifico. Il compilatore si rifiuterà di compilare questo codice . In questo caso, dobbiamo scrivere Cat.print((Integer)null) per chiamare il terzo metodo e Cat.print((String)null) per chiamare il quarto."

"È stato molto istruttivo. Grazie."

"Vorrei sottolineare che quando si determina il metodo corretto da chiamare, i tipi possono solo allargarsi. Non possono restringersi. Considera questo esempio:"

Codice
class Cat
{
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }

 public static void main(String[] args)
 {
  Cat.print((byte)1);
  Cat.print(1);
 }
}

Nel primo caso, il tipo di byte verrà allargato a short e verrà chiamato il primo metodo: void print(short n). .

Nel secondo caso, ci sarà una conversione di ampliamento implicita da int a Integer, e quindi verrà chiamato il secondo metodo: void print(Integer n). .

"Non me l'aspettavo."

"No, ecco la vera sorpresa:"

codice java Descrizione
class Cat
{
 public static void print(Object o)
 {
  System.out.println(o);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }

 public static void main(String[] args)
 {
  Cat.print(1);
  Cat.print(null);
 }
}
Nel primo caso, int verrà esteso a Integer. Poiché non esiste un metodo per Integer, il metodo più adatto (e quello chiamato) è void print(Object o)

Nel secondo caso, non ci saranno errori di compilazione e verrà chiamato void print(String s) , il che non è ovvio.

"Amigo, spero che tu capisca che in questi casi è meglio specificare un operatore di tipo cast (come abbiamo fatto con «(byte)») per sapere esattamente quale metodo verrà chiamato."

"Non mi sarei mai aspettato che i metodi sovraccaricassero i problemi. Ma poi arrivi tu. Grazie, Rishi. Terrò alta la guardia su questo punto."