CodeGym /Cursos /JAVA 25 SELF /Sobrecarga de métodos (overloading)

Sobrecarga de métodos (overloading)

JAVA 25 SELF
Nível 18 , Lição 1
Disponível

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.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION