Depuis la version 16 de Java, un nouveau type de structure de données appelé record a été introduit. Il s’agit d’une simplification du modèle classique de classe, spécialement conçu pour les objets immuables et les conteneurs de données. Comparons en détail les classes et les records en Java, leurs différences et leurs usages.
Une classe en Java est une structure qui permet de définir des objets avec des états (via des champs ou variables d’instance) et des comportements (via des méthodes). Une classe est très flexible et peut inclure des méthodes, des constructeurs, des blocs d’initialisation statiques, ainsi que des champs privés, publics, ou protégés.
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && name.equals(person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
toString()
, equals()
, et hashCode()
, ce qui entraîne beaucoup de code répétitif (boilerplate).Un record est une structure de données simplifiée introduite dans Java 16, destinée à remplacer les classes de type DTO (Data Transfer Object), qui sont souvent utilisées pour encapsuler des données sans comportement complexe. Les records sont conçus pour être immuables, et le compilateur génère automatiquement pour eux les méthodes toString()
, equals()
, et hashCode()
.
public record Person(String name, int age) {
// Le constructeur, les getters, toString, equals, et hashCode sont générés automatiquement
}
toString()
, equals()
, hashCode()
, ainsi que des constructeurs canoniques pour initialiser les champs.Caractéristique | Classe | Record |
---|---|---|
Mutabilité | Les classes peuvent être mutables ou immuables. | Les records sont immutables par défaut, les champs sont final . |
Code répétitif (boilerplate) | Nécessite des méthodes manuelles (toString , equals , etc.). | Génère automatiquement toString() , equals() , hashCode() , et un constructeur canonique. |
Constructeurs | Peut avoir plusieurs constructeurs avec différentes signatures. | Dispose d’un constructeur canonique généré automatiquement pour tous les champs. |
Héritage | Peut hériter d’autres classes et implémenter des interfaces. | Ne peut pas hériter d’une autre classe, mais peut implémenter des interfaces. |
Utilisation | Convient pour des objets complexes avec des comportements variés. | Convient aux modèles de données simples ou aux DTO immuables. |
Personnalisation | Permet de personnaliser le comportement (logique, mutabilité, etc.). | Limité à la gestion des données, moins de flexibilité pour ajouter des méthodes ou de la logique. |
Les classes sont appropriées lorsque :
Si tu dois créer une classe représentant un compte bancaire qui permet de modifier son solde et d’exécuter des opérations :
public class BankAccount {
private String accountHolder;
private double balance;
public BankAccount(String accountHolder, double balance) {
this.accountHolder = accountHolder;
this.balance = balance;
}
public void deposit(double amount) {
balance += amount;
}
public void withdraw(double amount) {
if (amount > balance) {
throw new IllegalArgumentException("Insufficient balance");
}
balance -= amount;
}
@Override
public String toString() {
return "BankAccount{accountHolder='" + accountHolder + "', balance=" + balance + "}";
}
}
Les records sont particulièrement utiles lorsque :
equals()
, hashCode()
, ou toString()
.Imaginons que tu dois stocker les informations d’un utilisateur sans logique métier spécifique :
public record User(String username, String email) {
// Constructeur, getters, equals, hashCode et toString sont générés automatiquement
}
Tu peux facilement créer des instances comme ceci :
User user = new User("john_doe", "john@example.com");
System.out.println(user.username()); // john_doe
Parfois, tu peux combiner des classes et des records dans un même projet pour différents types de besoins. Par exemple, un compte bancaire pourrait être une classe, tandis qu’un rapport financier ou un historique de transaction pourrait être un record.
public class BankAccount {
private String accountHolder;
private double balance;
public BankAccount(String accountHolder, double balance) {
this.accountHolder = accountHolder;
this.balance = balance;
}
public void deposit(double amount) {
balance += amount;
}
public void withdraw(double amount) {
if (amount > balance) {
throw new IllegalArgumentException("Insufficient balance");
}
balance -= amount;
}
public TransactionRecord createTransactionRecord(double amount, String type) {
return new TransactionRecord(amount, type, LocalDate.now());
}
}
public record TransactionRecord(double amount, String type, LocalDate date) {
}
En résumé, les classes en Java sont très flexibles et polyvalentes, permettant de définir à la fois des données et des comportements, tandis que les records se concentrent sur la simplification de la gestion des données immuables. Utiliser des records réduit le code répétitif et rend la gestion des données plus concise, mais si tu as besoin de mutabilité ou d’héritage, une classe sera plus appropriée.
Publié le 20/01/2025 dans Actualités
Rédigé par :