Fácil Java

Par genérico

Enunciado

Crie uma classe genérica Par<A, B> que armazena dois valores de tipos diferentes. Implemente métodos getPrimeiro(), getSegundo() e inverter() que retorna um novo Par<B, A> com os valores trocados. No main, crie um Par<String, Integer>, imprima os valores e depois o par invertido.

Requisitos

  • A classe Par deve ser genérica com dois parâmetros de tipo.
  • O método inverter() deve retornar Par<B, A>.
  • O programa deve imprimir os valores originais e os invertidos.

Código inicial

public class Main {
    public static void main(String[] args) {
        // TODO: criar Par<String, Integer> e testar
    }
}

// TODO: declarar classe Par<A, B>

Saída esperada

Primeiro: olá, Segundo: 42
Invertido: 42, olá
Ver dica

Use new Par<>(segundo, primeiro) dentro de inverter().

Mostrar solução
public class Main {
    public static void main(String[] args) {
        Par<String, Integer> par = new Par<>("olá", 42);
        System.out.println("Primeiro: " + par.getPrimeiro() + ", Segundo: " + par.getSegundo());
        Par<Integer, String> invertido = par.inverter();
        System.out.println("Invertido: " + invertido.getPrimeiro() + ", " + invertido.getSegundo());
    }
}

class Par<A, B> {
    private final A primeiro;
    private final B segundo;

    public Par(A primeiro, B segundo) {
        this.primeiro = primeiro;
        this.segundo = segundo;
    }

    public A getPrimeiro() { return primeiro; }
    public B getSegundo() { return segundo; }

    public Par<B, A> inverter() {
        return new Par<>(segundo, primeiro);
    }
}

Passo a passo

  1. Declaramos a classe Par<A, B> com dois parâmetros de tipo, permitindo armazenar quaisquer tipos.
  2. Os campos primeiro e segundo são do tipo A e B, respectivamente, e são final para imutabilidade.
  3. O construtor recebe valores dos tipos A e B e os atribui.
  4. Os getters retornam os valores com os tipos corretos, sem casts.
  5. O método inverter() cria um novo Par<B, A> trocando a ordem dos argumentos.
  6. No main, instanciamos Par<String, Integer> e imprimimos os valores.
  7. Chamamos inverter() e imprimimos o novo par, mostrando a troca de tipos.

Por que funciona

A classe genérica permite que os tipos A e B sejam definidos no momento da instanciação, garantindo segurança de tipos. O método inverter() usa os mesmos parâmetros de tipo da classe, mas em ordem trocada, e o compilador verifica se os tipos estão corretos. Como os genéricos são apagados em tempo de execução (type erasure), não há custo adicional em runtime.

Erros comuns

  • Esquecer de declarar os parâmetros de tipo na classe: class Par { ... } causaria uso de Object e perderia a segurança de tipos.
  • Tentar acessar primeiro diretamente sem getter, mas como é privado, não compila.
  • No main, usar new Par("olá", 42) sem os tipos explícitos ainda funciona por inferência, mas é boa prática declarar.
  • Retornar Par<A, B> em inverter() em vez de Par<B, A> causaria erro de tipo na atribuição.

Outra forma de resolver

Usar record (Java 16+) para simplificar:

record Par<A, B>(A primeiro, B segundo) {
    Par<B, A> inverter() { return new Par<>(segundo, primeiro); }
}

Saída esperada

Primeiro: olá, Segundo: 42
Invertido: 42, olá