CodeGym /Cursos /JAVA 25 SELF /Record com métodos

Record com métodos

JAVA 25 SELF
Nível 22, Lição 3
Disponível

1. Estendendo a classe record: métodos adicionais

Posso adicionar métodos a um record?

Claro! Um Record é como um apartamento já reformado: as paredes e o piso já estão prontos e não podem ser trocados, mas ninguém proíbe você de organizar os móveis do seu jeito. Dentro de um record você pode declarar métodos comuns, métodos estáticos e até armazenar constantes. Isso significa que a lógica de negócio não precisa ser movida para classes “utilitárias” separadas — ela pode ser integrada diretamente no próprio record.

Exemplo: método de cálculo da distância entre pontos

Suponha que temos um record para um ponto no plano:


public record Point(int x, int y) {
    // Método adicional
    public double distanceTo(Point other) {
        int dx = this.x - other.x;
        int dy = this.y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Agora você pode fazer assim:


Point p1 = new Point(0, 0);
Point p2 = new Point(3, 4);
System.out.println(p1.distanceTo(p2)); // 5.0

Como você pode ver, uma classe record pode ser “enriquecida” com seus próprios métodos — e isso é muito conveniente!

Exemplo: método estático


public record Rectangle(int width, int height) {
    public int area() {
        return width * height;
    }

    public static Rectangle square(int size) {
        return new Rectangle(size, size);
    }
}

Agora é possível criar um “quadrado” com uma única chamada:


Rectangle r = Rectangle.square(5);
System.out.println(r.area()); // 25

2. Construtor compacto e validação de dados

Para que serve o “construtor compacto”?

O construtor canônico de um record é criado automaticamente e atribui os parâmetros aos campos. Mas às vezes queremos adicionar uma verificação dos dados de entrada (por exemplo, proibir coordenadas negativas).

Em uma classe comum, escreveríamos:


public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        if (x < 0 || y < 0) throw new IllegalArgumentException();
        this.x = x;
        this.y = y;
    }
    // ...
}

Em um record, é possível declarar um construtor compacto — sem repetir a lista de parâmetros e sem atribuir os campos explicitamente (isso é feito pelo compilador).

Sintaxe do construtor compacto


public record Point(int x, int y) {
    public Point {
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("Coordinates must be non-negative");
        }
        // Não é necessário escrever: this.x = x; this.y = y;
    }
}
  • Os parâmetros do construtor coincidem automaticamente com os componentes do record.
  • As atribuições this.x = x e this.y = y são feitas pelo compilador automaticamente após a execução do corpo do construtor (ou após a saída bem-sucedida dele).
  • Se uma exceção for lançada, o objeto não será criado.

Exemplo com validação


Point p1 = new Point(3, 5); // OK
Point p2 = new Point(-1, 2); // Lança IllegalArgumentException!

Posso declarar um “construtor comum”?

Sim! Se você precisar criar um construtor com outra lista de parâmetros ou lógica adicional, declare-o explicitamente:


public record Range(int from, int to) {
    public Range(int size) {
        this(0, size); // chama o construtor principal
    }
}

3. Restrições de classes record

Ao contrário das classes comuns, as classes record têm uma série de restrições. É importante lembrar disso para não se surpreender com erros de compilação.

Apenas componentes — nenhum campo não estático adicional

Em uma classe record não é permitido declarar novos campos não estáticos:


public record Person(String name, int age) {
    // int id; // Erro de compilação! Não é permitido adicionar campos não estáticos.
}

É permitido declarar campos e métodos estáticos:


public record Person(String name, int age) {
    public static final String SPECIES = "Homo sapiens";
}

Record é sempre final

Uma classe Record não pode ser classe pai (não é possível herdar dela) e ela própria não pode estender explicitamente outra classe (exceto a herança implícita de java.lang.Record). Isso significa que uma classe record é sempre uma estrutura “final”.


public record User(String login) { }

// public class Admin extends User {} // Erro: não é possível herdar de um record!

É possível implementar interfaces

Uma classe Record pode implementar interfaces:


public interface Printable {
    void print();
}

public record Invoice(int amount) implements Printable {
    @Override
    public void print() {
        System.out.println("Valor: " + amount);
    }
}

4. Exemplos: records avançados em tarefas reais

Vamos analisar alguns exemplos práticos em que métodos adicionais e construtores compactos tornam a classe record realmente útil.

Record com método calculado


public record Circle(double x, double y, double radius) {
    public double area() {
        return Math.PI * radius * radius;
    }

    public double distanceTo(Circle other) {
        double dx = x - other.x;
        double dy = y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Record com validação


public record Email(String value) {
    public Email {
        if (value == null || !value.contains("@")) {
            throw new IllegalArgumentException("E-mail inválido: " + value);
        }
    }
}

Agora não é possível criar um e-mail inválido:


Email e1 = new Email("test@example.com"); // OK
Email e2 = new Email("not-an-email"); // Lança IllegalArgumentException

Record com métodos estáticos adicionais


public record Temperature(double celsius) {
    public static Temperature fromFahrenheit(double fahrenheit) {
        return new Temperature((fahrenheit - 32) * 5 / 9);
    }

    public double toFahrenheit() {
        return celsius * 9 / 5 + 32;
    }
}

Uso:


Temperature t = Temperature.fromFahrenheit(98.6);
System.out.println(t.celsius()); // 37.0
System.out.println(t.toFahrenheit()); // 98.6

5. Construtor compacto: nuances e restrições

Quando usar o construtor compacto?

  • Quando for necessário verificar a correção dos dados (validação).
  • Quando for necessário alterar valores antes de salvá-los (por exemplo, arredondar um número ou colocar uma string em maiúsculas).
  • Quando você quiser evitar duplicação da lista de parâmetros.

Características de funcionamento

  • No construtor compacto não é permitido atribuir valores aos componentes explicitamente (this.x = ...) — isso causará erro de compilação, pois o compilador faz a atribuição após a execução do corpo do construtor.
  • No construtor compacto não é possível alterar os nomes dos parâmetros — eles sempre coincidem com os nomes dos componentes do record.

Exemplo: arredondamento automático


public record Money(double amount) {
    public Money {
        amount = Math.round(amount * 100) / 100.0; // Arredondamos para centavos
    }
}

6. Prática: evoluindo o aplicativo didático

Suponha que estamos implementando operações bancárias em um aplicativo didático. Temos uma classe record Transaction, que armazena o valor, o remetente e o destinatário.


public record Transaction(String from, String to, double amount) {
    public Transaction {
        if (amount <= 0) throw new IllegalArgumentException("O valor deve ser positivo");
        if (from == null || to == null) throw new IllegalArgumentException("Os campos não podem ser null");
    }

    public String description() {
        return String.format("Transferência de %.2f de %s para %s", amount, from, to);
    }
}

Uso:


Transaction t = new Transaction("Alice", "Bob", 150.0);
System.out.println(t.description()); // Transferência de 150.00 de Alice para Bob

Uma tentativa de criar uma transação inválida resultará em erro:


Transaction t2 = new Transaction("Alice", "Bob", -10.0); // IllegalArgumentException

Tabela: o que pode e o que não pode em uma classe record

Permitido em uma classe record Não permitido em uma classe record
Métodos comuns Novos campos não estáticos
Métodos e campos estáticos Herdar de outras classes
Implementar interfaces Ser superclasse para outras classes
Construtores compactos e comuns Alterar componentes após a criação
Sobrescrever métodos Usar setters

7. Erros típicos ao trabalhar com classes record com corpo customizado

Erro nº 1: tentativa de adicionar um campo não estático.
Iniciantes muitas vezes tentam adicionar à classe record “mais um campo para a lógica interna” — por exemplo, um contador ou um cache. Isso não funciona: o compilador emitirá um erro imediatamente. Se você precisa manter estado adicional, provavelmente uma classe record não é a melhor escolha.

Erro nº 2: esquecer a validação no construtor compacto.
Se você quer que o objeto seja sempre válido, faça a verificação no construtor compacto. Não confie no fato de que “o usuário não vai digitar algo errado”.

Erro nº 3: tentar alterar um componente após a criação.
Os campos da classe record são final — não podem ser alterados nem diretamente nem por meio de métodos. Se você precisa de uma estrutura mutável, use uma classe comum.

Erro nº 4: duplicar a lógica no(s) método(s) e no construtor.
Às vezes a lógica de validação e a lógica de cálculo acabam duplicadas tanto em métodos quanto no construtor. É melhor concentrar toda a validação no construtor e deixar os métodos para a lógica de negócio “limpa”.

Erro nº 5: esquecer as restrições de herança.
Uma classe Record é sempre final — não é possível criar uma subclasse dela. Se você está projetando uma hierarquia que precisa de subclasses, use classes comuns.

1
Tarefa
JAVA 25 SELF, nível 22, lição 3
Bloqueado
Leituras do termômetro na estação meteorológica 🌡️
Leituras do termômetro na estação meteorológica 🌡️
1
Tarefa
JAVA 25 SELF, nível 22, lição 3
Bloqueado
Validação do endereço de e-mail durante o registro 📧
Validação do endereço de e-mail durante o registro 📧
1
Tarefa
JAVA 25 SELF, nível 22, lição 3
Bloqueado
Criação de um cartão de personagem com dados gerais 🧍
Criação de um cartão de personagem com dados gerais 🧍
1
Tarefa
JAVA 25 SELF, nível 22, lição 3
Bloqueado
Registro de transações financeiras no banco 💸
Registro de transações financeiras no banco 💸
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION