"Olá, amigo! Alguns dias atrás eu falei sobre métodos de sobrecarga. Você entendeu tudo?"

"Sim. Eu me lembro. Cada método de classe deve ser único. Um método de membro é único se a classe não tiver outro método com o mesmo nome e tipos de parâmetro (e a ordem dos parâmetros é importante)."

"Muito bem! Vejo que você aprendeu bem essa lição. Hoje quero expandir um pouco o seu conhecimento neste tópico. Que método você acha que será chamado em cada caso?"

Código
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);
 }
}

"É difícil dizer."

"No primeiro caso, 1 é um int . Temos uma correspondência de 100% com o método que recebe um int. O primeiro void print(int n) .

No segundo caso, não temos um método que receba um byte. Mas existem dois métodos que usam um short e um int. Com base nas regras de ampliação de tipo, um byte será primeiro ampliado para um curto e, em seguida, ampliado para um int. Assim, o veredicto é que o void imprime(short n). será chamado.

No terceiro caso, temos uma correspondência de 100% com o método que recebe uma String. A impressão void (String s). método será chamado.

O quarto caso é ambíguo. null não tem um tipo específico. O compilador se recusará a compilar este código . Nesse caso, precisamos escrever Cat.print((Integer)null) para chamar o terceiro método e Cat.print((String)null) para chamar o quarto."

"Isso foi muito informativo. Obrigado."

"Gostaria de salientar que, ao determinar o método correto a ser chamado, os tipos só podem ser ampliados. Eles não podem ser reduzidos. Considere este exemplo:"

Código
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);
 }
}

No primeiro caso, o tipo de byte será ampliado para um short e o primeiro método será chamado: void print(short n). .

No segundo caso, haverá uma conversão de ampliação implícita de int para Integer e, em seguida, o segundo método será chamado: void print(Integer n). .

"Eu não esperava isso."

"Não, aqui está a verdadeira surpresa:"

código Java Descrição
 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);
 }
}
No primeiro caso, int será estendido para Integer. Como não existe método para Integer, o método mais adequado (e o chamado) é void print(Object o)

No segundo caso, não haverá nenhum erro de compilação e void print(String s) será chamado, o que não é óbvio.

"Amigo, espero que você entenda que nesses casos é melhor especificar um operador type cast (como fizemos com «(byte)») para saber exatamente qual método será chamado."

"Eu nunca esperei que nenhum problema viesse de métodos de sobrecarga. Mas então você aparece. Obrigado, Rishi. Vou manter minha guarda neste ponto."