」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > Java 中的記錄與類別

Java 中的記錄與類別

發佈於2024-11-02
瀏覽:432

Records vs Clases en Java

如果您已经了解 Java 中的 records,您可能会发现它的用法与类非常相似,但是有一些重要的差异必须考虑。在本文中,我们将了解 Java 中的 recordsclasses 之间的差异。如果您仍然不知道记录,我建议阅读我的帖子《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 方法。

记录和类之间有什么区别?

  • 不可变性records是不可变的,也就是说,一旦创建了record类型的对象,它的属性就不能被修改。相反,类可能是不变的,也可能不是不变的,具体取决于它的实现方式。
  • 生成的方法records自动生成equals、hashCode和toString方法,以及每个属性的getter方法。然而,在类中,这些方法必须手动实现或借助 IDE 实现。
  • 在OOP中使用记录不能从其他类继承,也不能被其他类扩展,但它们可以实现接口。另一方面,类可以从其他类继承、扩展,并且通常非常适合涵盖面向对象编程的概念。
  • 语法记录的语法比类简单,因为它可以在一行中定义,而类需要多行代码。
  • 目的记录是一种类似于DTO(数据传输对象)的结构,即帮助建模不可变数据的类,其本身是 是一个更通用的结构,可以有行为和状态。

何时使用记录,何时使用类?

如果需要的是一个不可变的数据结构来存储数据,并且不需要对属性进行任何修改(简单地看成是一个携带信息的对象)。另一方面,如果您需要具有独特逻辑和特定方法的更通用的结构、面向对象范例的方法、应用设计模式或使用 JPA 或 Hibernate 等,那么您应该使用类。

额外:具有可变属性的记录

让我们考虑以下示例,有两条记录 Product,其属性为名称和价格,还有 Cart,其具有 ArrayList 类型的单个属性 products 以及一些获取产品数量和购物车总数的方法。

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 products) {

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

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

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

这种情况下的问题是,每个 record 本身都是不可变的,但在记录 Cart 的情况下,它具有 ArrayList 类型的属性,并且由于 ArrayList 本质上是可变的,记录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());
    }
}

上面的代码编译没有问题,因为只修改了列表的内容,但产品属性本身没有被修改。这只是特定情况的示例,可能没有必要,但很高兴知道可以这样做。

版本聲明 本文轉載於:https://dev.to/asjordi/records-vs-clases-en-java-1bb6?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3