Maison  >  Article  >  Java  >  Enregistrements vs classes en Java

Enregistrements vs classes en Java

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-10-17 06:09:02682parcourir

Records vs Clases en Java

Wenn Sie Datensätze in Java bereits kennen, werden Sie feststellen, dass die Verwendung der von Klassen sehr ähnlich ist, es gibt jedoch wichtige Unterschiede, die berücksichtigt werden müssen. In diesem Artikel werden wir die Unterschiede zwischen Datensätzen und Klassen in Java sehen. Wenn Sie Datensätze immer noch nicht kennen, empfehle ich Ihnen, meinen Beitrag „Datensätze in Java: Was sie sind und wie man sie verwendet“ zu lesen.

Unveränderlichkeit

Ein unveränderliches Objekt ist eines, dessen Attribute nach der Erstellung des Objekts nicht mehr geändert werden können. Im Fall von Datensätzen sind diese unveränderlich, d. h. sobald ein Objekt vom Typ Datensatz erstellt wurde, können seine Attribute nicht mehr geändert werden. Andererseits kann eine Klasse je nach Implementierung unveränderlich sein oder auch nicht. Dieser Teil stellt die Integrität der Daten sicher und verhindert, dass sie versehentlich geändert werden.

Zweck

Klassen werden im Allgemeinen einfach geschrieben, um Daten zu speichern, beispielsweise die aus einer Datenbankabfrage oder die Daten aus einem Formular. In vielen Fällen sind diese Daten unveränderlich, da die Gültigkeit der Daten ohne Verwendung einer Synchronisierung sichergestellt werden muss. Um dies zu erreichen, wird eine Klasse mit den folgenden Elementen geschrieben:

  • Private Attribute für jedes Feld.
  • Getter für jedes Feld.
  • Ein Konstruktor, der alle Felder initialisiert.
  • Eine Gleichheitsmethode, die Objekte auf Gleichheit vergleicht.
  • Eine HashCode-Methode, die einen Hash-Code basierend auf den Feldern generiert.
  • Eine toString-Methode, die eine Zeichenfolgendarstellung der Felder generiert.

Wenn Sie beispielsweise eine Personenklasse mit den beiden Attributen „Name“ und „Nachname“ haben, könnten Sie diese wie folgt schreiben:

public class Person {

    private final String name;
    private final String lastName;

    public Person(String name, String lastName) {
        this.name = name;
        this.lastName = lastName;
    }

    public String getName() {
        return name;
    }

    public String getLastName() {
        return lastName;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person person)) return false;
        return Objects.equals(getName(), person.getName()) && Objects.equals(getLastName(), person.getLastName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getLastName());
    }
}

Dies ist eine Lösung für die Aufgabe, aber es ist eine Menge Code für das, was tatsächlich benötigt wird. Wenn die Klasse mehr Attribute hätte, würde das Schreiben des Codes noch länger dauern, selbst wenn dies mit Hilfe einer IDE oder eines Plugins wie GitHub Copilot erfolgen würde. Eine bessere Lösung wäre, unsere Klasse als Datenklasse zu deklarieren, also als eine Klasse, die nur Daten speichert und kein bestimmtes Verhalten haben muss, und hier kommen Datensätze ins Spiel.

Auf diese Weise könnte die Person-Klasse wie folgt als Datensatz umgeschrieben werden:

public record Person(String name, String lastName) { }

Dadurch werden automatisch die Methoden „equals“, „hashCode“ und „toString“ sowie die Getter-Methoden für jedes der Attribute generiert.

Was sind die Unterschiede zwischen einem Datensatz und einer Klasse?

  • Unveränderlichkeit: Die Datensätze sind unveränderlich, d. h. sobald ein Objekt vom Typ Datensatz erstellt wurde, können seine Attribute nicht mehr geändert werden. Stattdessen kann eine Klasse unveränderlich sein oder auch nicht, je nachdem, wie sie implementiert wurde.
  • Generierte Methoden: Die Datensätze generieren automatisch die Methoden equal, hashCode und toString sowie die Getter-Methoden für jedes der Attribute. In Klassen hingegen müssen diese Methoden manuell oder mit Hilfe einer IDE implementiert werden.
  • Verwendung in OOP: Datensätze können nicht von anderen Klassen erben oder durch andere Klassen erweitert werden, sie können jedoch Schnittstellen implementieren. Andererseits können Klassen von anderen erben, erweitert werden und sind im Allgemeinen ideal, um die Konzepte der objektorientierten Programmierung abzudecken.
  • Syntax: Die Syntax eines Datensatzes ist einfacher als die einer Klasse, da sie in einer einzigen Zeile definiert werden kann, während eine Klasse mehrere Zeilen Code erfordert.
  • Zweck: Die Datensätze sind eine Struktur, die einem DTO (Data Transfer Object) ähnelt, also einer Klasse, die dabei hilft, unveränderliche Daten zu modellieren, ihrerseits eine Klasse ist eine allgemeinere Struktur, die Verhalten und Zustand haben kann.

Wann sollte ein Datensatz und wann eine Klasse verwendet werden?

Wenn eine unveränderliche Datenstruktur zum Speichern von Daten erforderlich ist und keine Änderungen an den Attributen vorgenommen werden müssen (es wird lediglich als Objekt zum Übertragen von Informationen betrachtet). Wenn Sie hingegen eine allgemeinere Struktur mit eindeutiger Logik und spezifischen Methoden, einen Ansatz für ein objektorientiertes Paradigma, die Anwendung von Entwurfsmustern oder die Arbeit mit JPA oder Hibernate usw. benötigen, sollten Sie eine Klasse verwenden.

Extra: Record con atributos mutables

Consideremos el siguiente ejemplo, se tienen dos records Product con los atributos name y price, y Cart con un solo atributo products del tipo ArrayList y algunos métodos para obtener la cantidad de productos y el total del carrito.

package org.jordi.example;

public record Product(String name, double price) { }
package org.jordi.example;

import java.util.ArrayList;
import java.util.List;

public record Cart(List<Product> products) {

    public Cart() {
        this(new ArrayList<>());
    }

    public int getQuantity() {
        return this.products.size();
    }

    public double getTotal() {
        return this.products.stream().mapToDouble(Product::price).sum();
    }
}

La cuestión en este caso es que cada uno de los record es inmutable por sí mismo, pero en el caso del record Cart al tener un atributo del tipo ArrayList<> y dado que por naturaleza un ArrayList es mutable, se puede modificar el contenido de la lista una vez que se crea una instancia del record Cart.

package org.jordi.example;

public class Main {
    public static void main(String[] args) {
        Product water = new Product("Water", 15);
        Product milk = new Product("Milk", 22);

        Cart cart = new Cart();
        cart.products().add(water);
        cart.products().add(milk);
        System.out.println("Price: " + cart.getTotal());

        cart.products().clear();
        System.out.println("Quantity: " + cart.getQuantity());
        System.out.println("Price: " + cart.getTotal());
    }
}

El código anterior compila sin problemas, ya que solo se está modificando el contenido de la lista, pero no se está modificando el atributo products en sí. Este solo es un ejemplo para un caso particular, que probablemente no sea necesario, pero es bueno saber que esto se puede realizar.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:Écrire un opérateur en JavaArticle suivant:Écrire un opérateur en Java