Menu

Sobrecarga de métodos em Java: mesmo nome, parâmetros diferentes

Como a sobrecarga de métodos em Java permite que vários métodos compartilhem um nome mas recebam parâmetros diferentes, como o compilador escolhe uma sobrecarga e quais armadilhas de ambiguidade evitar.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Um nome, várias versões

Na página anterior você viu como os parâmetros de um método definem o que ele aceita. A sobrecarga de métodos vai além: você pode dar a vários métodos o mesmo nome, desde que suas listas de parâmetros sejam diferentes. O compilador os trata como métodos distintos e escolhe o correto com base nos argumentos que você passa.

É por isso que System.out.println imprime tranquilamente um int, uma String, um boolean ou um double: não existe um único println, e sim muitas sobrecargas que compartilham o nome. Você escreve a chamada que pretende e o compilador a associa à versão que se encaixa.

Os dois métodos se chamam square, mas um recebe um int e o outro um double. O literal 5 é um int, então a primeira sobrecarga é executada; 2.5 é um double, então a segunda é executada.

O que conta como uma sobrecarga diferente

As sobrecargas precisam diferir na lista de parâmetros, ou seja, em pelo menos um destes pontos:

  • um número diferente de parâmetros,
  • tipos de parâmetros diferentes, ou
  • uma ordem diferente dos tipos.

Cada chamada tem uma lista de parâmetros que corresponde exatamente a um dos três métodos join, então não há confusão.

O tipo de retorno não conta

Uma armadilha comum para iniciantes: tentar sobrecarregar apenas pelo tipo de retorno. O tipo de retorno não faz parte da assinatura que o compilador usa, então isto não compila:

// NÃO compila - mesmo nome, mesmos parâmetros, só muda o tipo de retorno
static int   value() { return 1; }
static double value() { return 1.0; }   // erro: value() já está definido

O compilador não consegue distinguir os dois, porque em um ponto de chamada como value() nada nos argumentos indica qual você quer. Você pode dar tipos de retorno diferentes às sobrecargas, mas apenas quando suas listas de parâmetros já forem diferentes.

Como o Java escolhe uma sobrecarga

Quando mais de uma sobrecarga poderia aceitar seus argumentos, o Java escolhe a mais específica e prefere uma correspondência exata de tipo a uma conversão de ampliação. Veja o que acontece com um argumento int:

show(7) corresponde exatamente a int, mesmo que long e double também pudessem conter um 7 após uma ampliação. Só se a sobrecarga exata fosse removida é que o compilador ampliaria int para long e depois para double. Essa resolução é decidida inteiramente em tempo de compilação, com base nos tipos declarados dos seus argumentos.

Cuidado com chamadas ambíguas

Se nenhuma sobrecarga for claramente a melhor correspondência, o compilador se recusa a adivinhar e relata um erro. Isso acontece com mais frequência com null, que se encaixa em qualquer tipo de referência:

static void handle(String s) { }
static void handle(StringBuilder b) { }

handle(null);   // erro: a referência a handle é ambígua

As duas sobrecargas aceitam null e nenhuma é mais específica, então a chamada não compila. Corrija tornando o tipo explícito com um cast - handle((String) null) - ou redesenhando para que as sobrecargas não colidam. O mesmo cuidado vale ao misturar autoboxing e ampliação; mantenha os conjuntos de sobrecargas simples o suficiente para que toda chamada tenha um vencedor óbvio.

Sobrecarga de construtores

A sobrecarga não se limita a métodos comuns: os construtores a usam o tempo todo para oferecer várias formas de construir um objeto. Um construtor sem argumentos pode delegar para um mais completo com this(...):

Os dois construtores compartilham o nome Point, mas diferem no número de parâmetros, exatamente como métodos sobrecarregados. Delegar com this(...) mantém a lógica de inicialização em um único lugar.

Sobrecarga vs sobrescrita

Os dois termos soam parecidos, mas não têm relação:

  • Sobrecarga - mesmo nome, listas de parâmetros diferentes, na mesma classe. O compilador escolhe a versão em tempo de compilação. Trata-se de oferecer variantes de uma operação.
  • Sobrescrita - uma subclasse redefine um método herdado com o mesmo nome e os mesmos parâmetros. O Java escolhe a versão em tempo de execução com base no tipo real do objeto. Trata-se de substituir comportamento (você vai encontrá-la em herança e polimorfismo).

Se as listas de parâmetros forem idênticas, você está sobrescrevendo (ou causando um erro de método duplicado na mesma classe); se forem diferentes, você está sobrecarregando.

A seguir: Varargs

A sobrecarga permite escrever join(a, b) e join(a, b, c) como métodos separados, mas e se você quiser aceitar qualquer número de argumentos sem declarar uma sobrecarga para cada quantidade? A sintaxe de varargs do Java permite que um único método receba uma lista de argumentos de tamanho variável, e esse é o tema da próxima página.

Perguntas frequentes

O que é sobrecarga de métodos em Java?

Sobrecarga de métodos significa definir vários métodos com o mesmo nome dentro da mesma classe, cada um com uma lista de parâmetros diferente (número diferente de parâmetros, tipos diferentes ou ordem diferente dos tipos). O compilador decide qual versão chamar comparando os argumentos que você passa com os parâmetros de cada sobrecarga. É uma decisão tomada em tempo de compilação, não em tempo de execução.

Dois métodos podem diferir apenas pelo tipo de retorno em Java?

Não. O tipo de retorno não faz parte da assinatura de um método para fins de sobrecarga, então int total() e double total() na mesma classe geram um erro de compilação. As sobrecargas precisam diferir na lista de parâmetros: no número, nos tipos ou na ordem dos parâmetros. O tipo de retorno pode ser diferente, mas apenas além de uma diferença nos parâmetros, nunca sozinho.

Qual é a diferença entre sobrecarga e sobrescrita em Java?

Sobrecarga são vários métodos com o mesmo nome mas parâmetros diferentes na mesma classe, resolvidos pelo compilador em tempo de compilação. Sobrescrita é uma subclasse redefinindo um método herdado com o mesmo nome e os mesmos parâmetros, resolvido em tempo de execução com base no tipo real do objeto. A sobrecarga trata de oferecer variantes; a sobrescrita trata de substituir comportamento.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR