首页  >  文章  >  Java  >  Java 中的记录与类

Java 中的记录与类

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-17 06:09:02762浏览

Records vs Clases en Java

如果您已經了解 Java 中的 records,您可能會發現它的用法與類別非常相似,但必須考慮到一些重要的差異。在本文中,我們將了解 Java 中記錄類別之間的差異。如果您仍然不知道記錄,我建議閱讀我的文章《Java 中的記錄:它們是什麼以及如何使用它們》。

不變性

不可變對像是指一旦建立對象,其屬性就無法修改的對象。對於 records 來說,它們是不可變的,也就是說,一旦創建 record 類型的對象,其屬性就無法修改。另一方面,類別可能是不變的,也可能不是不變的,這取決於它的實作方式。這部分確保資料的完整性並防止其被意外修改。

目的

類別通常只是為了儲存資料而編寫,例如來自資料庫查詢的資料或來自表單的資料。在許多情況下,該數據是不可變的,因為需要在不使用同步的情況下確保數據的有效性。為了實現這一點,使用以下元素編寫一個類別:

  • 每個欄位的私有屬性。
  • 每個欄位的獲取器。
  • 初始化所有欄位的建構子。
  • 比較物件是否相等的 equals 方法。
  • hashCode 方法,根據欄位產生雜湊碼。
  • 一個 toString 方法,用於產生欄位的字串表示形式。

例如,如果你有一個 Person 類,有兩個屬性 name 和 lastName,你可以這樣寫:

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());
    }
}

這是該任務的解決方案,但它是實際需要的大量程式碼。如果類別具有更多屬性,即使在 IDE 或 GitHub Copilot 等插件的幫助下完成,編寫的程式碼也會更長。更好的解決方案是將我們的類別聲明為資料類,即僅儲存資料的類,並且不必具有特定行為,這就是 records 的用武之地。

這樣,Person 類別就可以改寫為記錄,如下圖:

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

這會自動產生 equals、hashCode 和 toString 方法,以及每個屬性的 getter 方法。

記錄和類別之間有什麼區別?

  • 不可變性記錄是不可變的,也就是說,記錄類型的物件一旦創建,其屬性就無法修改。相反,類別可能是不變的,也可能不是不變的,這取決於它的實作方式。
  • 產生方法記錄自動產生equals、hashCode和toString方法,以及每個屬性的getter方法。另一方面,在類別中,這些方法必須手動實作或藉助 IDE 實作。
  • 在OOP中使用記錄不能繼承其他類,也不能被其他類別擴展,但可以實現介面。另一方面,類別可以從其他類別繼承、擴展,並且通常非常適合涵蓋物件導向程式設計的概念。
  • 語法記錄的語法比類別更簡單,因為它可以在一行中定義,而類別需要多行程式碼。
  • 用途記錄是一種類似DTO(資料傳輸物件)的結構,即幫助建模不可變資料的類,其一部分是類別 是一個更通用的結構,可以有行為和狀態。

何時使用記錄,何時使用類別?

如果需要的是一個不可變的資料結構來儲存數據,並且不需要對屬性進行修改(簡單地看成是一個攜帶資訊的物件)。另一方面,如果您需要一個具有獨特邏輯和特定方法的更通用的結構、一種物件導向範例的方法、應用設計模式或使用 JPA 或 Hibernate 等,那麼您應該使用類別。

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.

以上是Java 中的记录与类的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn