1. Sobrecarga de métodos
Sobrecarga de métodos (method overloading) é a possibilidade de declarar em uma única classe vários métodos com o mesmo nome, mas com listas de parâmetros diferentes (tipos, quantidade ou ordem dos argumentos). Quando você chama esse método, o compilador decide qual versão usar, dependendo dos argumentos passados.
Uma analogia com a vida real
Imagine que você liga para o suporte do banco. Você pode ligar para números diferentes — para pessoas físicas, para pessoas jurídicas, para clientes VIP. Os números são diferentes, mas o objetivo é o mesmo — obter ajuda. Em programação, a sobrecarga de métodos é como um único número de suporte que conecta você automaticamente ao operador certo dependendo da sua questão (ou dos parâmetros que você passou).
Sintaxe de sobrecarga em Java
Em Java, a sobrecarga de métodos é bem simples: você declara vários métodos com o mesmo nome, mas com parâmetros diferentes.
Regra importante:
A sobrecarga difere apenas pela lista de parâmetros (tipo, quantidade, ordem).
Sobrecarga apenas pelo tipo de retorno não é permitida!
O compilador não consegue distinguir métodos se eles tiverem o mesmo nome e os mesmos parâmetros, mesmo que o tipo de retorno seja diferente.
Exemplo simples
public class Printer {
// Imprimir número inteiro
void print(int x) {
System.out.println("int: " + x);
}
// Imprimir string
void print(String s) {
System.out.println("String: " + s);
}
// Imprimir dois números
void print(int x, int y) {
System.out.println("int, int: " + x + ", " + y);
}
}
Uso:
Printer printer = new Printer();
printer.print(42); // chamará print(int x)
printer.print("Hello!"); // chamará print(String s)
printer.print(5, 10); // chamará print(int x, int y)
O compilador determina sozinho qual método chamar, com base nos argumentos passados.
2. Como o compilador escolhe o método correto
Quando você chama um método sobrecarregado, o compilador analisa a lista de argumentos e procura a versão mais adequada.
Critérios de seleção:
- Correspondência pela quantidade de argumentos.
- Correspondência pelo tipo de cada argumento (ou possibilidade de converter o tipo, por exemplo, int → double).
- Se vários métodos servirem, o mais específico é escolhido.
Exemplo:
public class OverloadDemo {
void show(int x) {
System.out.println("show(int): " + x);
}
void show(double x) {
System.out.println("show(double): " + x);
}
public static void main(String[] args) {
OverloadDemo demo = new OverloadDemo();
demo.show(5); // show(int): 5
demo.show(5.5); // show(double): 5.5
}
}
Se você chamar demo.show(5), o compilador escolherá show(int). Se chamar com 5.5 — escolherá show(double).
Conversões de tipos
Se não houver um método adequado, o compilador tentará converter os tipos dos argumentos (por exemplo, int → double), mas apenas se isso for possível e não ambíguo.
void print(double x) { /* ... */ }
print(5); // int 5 é convertido em double 5.0
Sobrecarga apenas pelo tipo de retorno — não funciona!
Muitos iniciantes tentam fazer assim:
// Erro! Esse tipo de sobrecarga não é possível
int sum(int x, int y) { return x + y; }
double sum(int x, int y) { return (double) (x + y); }
O compilador não entenderá qual método você quer chamar se você simplesmente escrever sum(2, 3).
Lembre-se: a sobrecarga de métodos só é possível pelos parâmetros, e não pelo tipo de retorno!
3. Sobrecarga de construtores
Você pode sobrecarregar não apenas métodos comuns, mas também construtores!
public class Person {
String name;
int age;
// Construtor apenas com nome
public Person(String name) {
this.name = name;
this.age = 0; // padrão
}
// Construtor com nome e idade
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Uso:
Person p1 = new Person("Anna");
Person p2 = new Person("Boris", 25);
4. Exemplos práticos
Calculator com sobrecarga
Vamos escrever uma classe Calculator que saiba somar números de tipos e quantidades diferentes.
public class Calculator {
// Soma de dois inteiros
int add(int a, int b) {
return a + b;
}
// Soma de três inteiros
int add(int a, int b, int c) {
return a + b + c;
}
// Soma de dois double
double add(double a, double b) {
return a + b;
}
}
Uso:
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // 5
System.out.println(calc.add(1, 2, 3)); // 6
System.out.println(calc.add(2.5, 3.1)); // 5.6
Sobrecarga de métodos na biblioteca padrão
Você já se deparou com sobrecarga, mesmo que não tenha percebido. Por exemplo, o método println em System.out é sobrecarregado para diferentes tipos:
System.out.println("Hello"); // println(String)
System.out.println(123); // println(int)
System.out.println(3.14); // println(double)
System.out.println(true); // println(boolean)
Abra o código-fonte da classe PrintStream — você verá dezenas de versões sobrecarregadas de println.
5. Quando usar sobrecarga
A sobrecarga de métodos é uma ferramenta poderosa, mas deve ser usada com sabedoria. Ela é útil quando:
- A lógica do método é a mesma, mas os parâmetros podem variar.
- Você quer tornar a API da classe mais amigável e flexível.
- É necessário suportar variantes antigas e novas de chamada do método.
Exemplo prático:
No nosso aplicativo didático (por exemplo, em um gerenciador de tarefas) é possível implementar um método para adicionar tarefas com parâmetros diferentes:
public class TaskManager {
void addTask(String description) { ... }
void addTask(String description, int priority) { ... }
void addTask(String description, int priority, String deadline) { ... }
}
Essa abordagem não só é conveniente para quem usa o seu código, como também torna sua classe flexível para mudanças futuras.
6. Sobrecarga e varargs (número variável de argumentos)
Em Java é possível declarar um método com número variável de parâmetros usando ... (varargs):
void printAll(String... messages) {
for (String msg : messages) {
System.out.println(msg);
}
}
Agora você pode chamar:
printAll("Hello");
printAll("One", "Two", "Three");
Também é possível sobrecarregar com varargs, mas tenha cuidado: se houver dois métodos e um deles usar varargs, enquanto o outro tiver número fixo de parâmetros, o compilador tentará primeiro encontrar uma correspondência exata.
7. Erros típicos ao sobrecarregar métodos
Erro nº 1: Confusão com os tipos de argumentos.
Se você tiver métodos void process(int x) e void process(double x), a chamada process(5) chamará a primeira versão, e process(5.0) — a segunda. Mas se você chamar process(5L), o compilador buscará a melhor correspondência e pode escolher uma sobrecarga não óbvia (ou até mesmo informar ambiguidade).
Erro nº 2: Sobrecarga com autoboxing.
Se você tiver void foo(Integer x) e void foo(Long x), a chamada foo(5) resultará em erro de compilação — o compilador não sabe qual método escolher, porque 5 pode ser convertido tanto para Integer quanto para Long.
Erro nº 3: Sobrecarga apenas pelo tipo de retorno.
Como já mencionado acima, métodos que se diferenciam apenas pelo tipo de retorno não podem ser sobrecarregados.
Erro nº 4: Sobrecarga e herança.
Se um método for declarado na classe base e, na subclasse, você declarar um método com o mesmo nome, mas com outra assinatura, isso será sobrecarga, não sobrescrita. Isso é frequentemente confundido! Mais detalhes sobre isso — na próxima aula.
GO TO FULL VERSION