”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Java 中的记录与类

Java 中的记录与类

发布于2024-11-02
浏览:682

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]删除
最新教程 更多>
  • 同实例无需转储复制MySQL数据库方法
    同实例无需转储复制MySQL数据库方法
    在同一实例上复制一个MySQL数据库而无需转储在同一mySQL实例上复制数据库,而无需创建InterMediate sqql script。以下方法为传统的转储和IMPORT过程提供了更简单的替代方法。 直接管道数据 MySQL手动概述了一种允许将mysqldump直接输出到MySQL clie...
    编程 发布于2025-05-26
  • 为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    查询模式实现缺失:解决“无法找到”错误在银光应用程序中,尝试使用LINQ建立错误的数据库连接的尝试,无法找到以查询模式的实现。”当省略LINQ名称空间或查询类型缺少IEnumerable 实现时,通常会发生此错误。 解决问题来验证该类型的质量是至关重要的。在此特定实例中,tblpersoon可能需...
    编程 发布于2025-05-26
  • 在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在C中的显式删除 在C中的动态内存分配时,开发人员通常会想知道是否需要手动调用“ delete”操作员在heap-exprogal exit exit上。本文深入研究了这个主题。 在C主函数中,使用了动态分配变量(HEAP内存)的指针。当应用程序退出时,此内存是否会自动发布?通常,是。但是,即使在这...
    编程 发布于2025-05-26
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-05-26
  • 如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    Red: How to Redirect Multiple User Types to Respective ActivitiesUnderstanding the ProblemIn a Firebase-based voting app with three distinct user type...
    编程 发布于2025-05-26
  • PHP与C++函数重载处理的区别
    PHP与C++函数重载处理的区别
    作为经验丰富的C开发人员脱离谜题,您可能会遇到功能超载的概念。这个概念虽然在C中普遍,但在PHP中构成了独特的挑战。让我们深入研究PHP功能过载的复杂性,并探索其提供的可能性。在PHP中理解php的方法在PHP中,函数超载的概念(如C等语言)不存在。函数签名仅由其名称定义,而与他们的参数列表无关。...
    编程 发布于2025-05-26
  • 在GO中构造SQL查询时,如何安全地加入文本和值?
    在GO中构造SQL查询时,如何安全地加入文本和值?
    在go中构造文本sql查询时,在go sql queries 中,在使用conting and contement和contement consem per时,尤其是在使用integer per当per当per时,per per per当per. [&​​&&&&&&&&&&&&&&&默元组方法在...
    编程 发布于2025-05-26
  • 用户本地时间格式及时区偏移显示指南
    用户本地时间格式及时区偏移显示指南
    在用户的语言环境格式中显示日期/时间,并使用时间偏移在向最终用户展示日期和时间时,以其localzone and格式显示它们至关重要。这确保了不同地理位置的清晰度和无缝用户体验。以下是使用JavaScript实现此目的的方法。方法:推荐方法是处理客户端的Javascript中的日期/时间格式化和时...
    编程 发布于2025-05-26
  • Go web应用何时关闭数据库连接?
    Go web应用何时关闭数据库连接?
    在GO Web Applications中管理数据库连接很少,考虑以下简化的web应用程序代码:出现的问题:何时应在DB连接上调用Close()方法?,该特定方案将自动关闭程序时,该程序将在EXITS EXITS EXITS出现时自动关闭。但是,其他考虑因素可能保证手动处理。选项1:隐式关闭终止数...
    编程 发布于2025-05-26
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。要解决此问题并确保在后续页面访问中执行脚本,Firefox用户应设置一个空功能。 警报'); }; alert('inline Alert')...
    编程 发布于2025-05-26
  • Android如何向PHP服务器发送POST数据?
    Android如何向PHP服务器发送POST数据?
    在android apache httpclient(已弃用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    编程 发布于2025-05-26
  • 您如何在Laravel Blade模板中定义变量?
    您如何在Laravel Blade模板中定义变量?
    在Laravel Blade模板中使用Elegance 在blade模板中如何分配变量对于存储以后使用的数据至关重要。在使用“ {{}}”分配变量的同时,它可能并不总是最优雅的解决方案。幸运的是,Blade通过@php Directive提供了更优雅的方法: $ old_section =“...
    编程 发布于2025-05-26
  • 如何使用Python理解有效地创建字典?
    如何使用Python理解有效地创建字典?
    在python中,词典综合提供了一种生成新词典的简洁方法。尽管它们与列表综合相似,但存在一些显着差异。与问题所暗示的不同,您无法为钥匙创建字典理解。您必须明确指定键和值。 For example:d = {n: n**2 for n in range(5)}This creates a dicti...
    编程 发布于2025-05-26
  • CSS强类型语言解析
    CSS强类型语言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    编程 发布于2025-05-26

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3