Record

Java 14 中引入了 Record 类(记录类型),Records 旨在简化和改进 Java 类的定义。Record 是一种特殊类型的 Java 类,用来创建不可变类。

在任何时候创建 Java 类时,我们都会创建大量的样板代码,我们可能做如下工作:

  • 为每个字段提供 setget 方法

  • 提供公共的构造方法。

  • 重写 hashCodetoString()equals()方法

Java Record 避免上述的样板代码,有如下特点:

  • 带有全部参数的构造方法。

  • public 访问器。

  • toString()hashCode()equals()

  • setget 方法。没有遵循 Bean 的命名规范。

  • final 类,不能继承 RecordRecord 为隐式的 final 类。除此之外与普通类一样。

  • 不可变类,通过构造创建 Record

  • final 属性,不可修改。

  • 不能声明实例属性,能声明 static 成员

创建 Record

public record Student(Integer id,String name,String email,Integer age) {
}

Record 通过构造方法创建了只读的对象,能够读取每个属性,不能设置新的属性值。 Record 用于创建不可变的对象,同时减少了样板代码。Record 对每个属性提供了 public 访问器,例如 lisi.name()

Student student = new Student(1, "zhangsan", "zhangsan@example.com", 18);
student.name; // zhangsan

普通方法 & 静态方法

public record Student(Integer id,String name,String email,Integer age) {
    public String print() {
        return String.format("id:%d,name:%s,email:%s,age:%d", id, name, email, age);
    }
    
    // 静态方法
    public static String emailUpperCase(String email) {
        return Optional.ofNullable(email).orElse("no email").toUpperCase();
    }
}

构造方法

我们可以在 Record 中添加构造方法,有三种类型的构造方法:

  • 紧凑构造方法:紧凑型构造方法是没有任何参数,甚至没有括号的构造方法。

  • 规范构造方法:规范构造方法是以所有成员作为参数。

  • 定制构造方法:定制构造方法是自定义参数个数。

record Student(Integer id, String name, String email, Integer age) {
    // 紧凑构造方法
    public Student {
        System.out.println("Student constructor");
    }
    // 定制构造方法
    public Student(Integer id, String email) {
        this(id, null, email, null);
    }
}

Record 与 Lombok

Record

  • 引入时间: Java 14 中引入。

  • 用途: 用于简化和改进 Java 类的定义,主要用于创建不可变的数据传输对象(DTO)或值对象。

  • 特性: 自动生成的 equals()hashCode()toString() 方法。

  • 成员变量是 final,不可修改。

  • 语法简洁,定义时自动生成很多常用方法。

Lombok

  • 引入时间: 提供很长一段时间,并作为库使用。

  • 用途:通过注解来减少样板代码的编写。

  • 特性:通过注解(如 @Getter@Setter@EqualsAndHashCode@ToString 等)自动生成常用方法。

  • 允许可变类(非 final 字段)。 需要在编译时使用 Lombok 插件支持。

Record 实现接口

Record 与普通类一样,可以实现接口,重写接口的方法。

public static String emailUpperCase(String email) {
    return Optional.ofNullable(email).orElse("no email").toUpperCase();
}
public record Student(Integer id, String name, String email, Integer age) implements IStudent {
    @Override
    public void print() {
        String str = String.format("id:%d,name:%s,email:%s,age:%d", id, name, email, age);
        System.out.println(str);
    }
}

局部 Record

Record 可以作为局部对象使用。在代码块中定义并使用。

public static void main(String[] args) {
    record Student(Integer id, String name, String email, Integer age) implements IStudent {
        @Override
        public void print() {
            String str = String.format("id:%d,name:%s,email:%s,age:%d", id, name, email, age);
            System.out.println(str);
        }
    }
    
    Student student = new Student(1, "zhangsan", "zhangsan@example.com", 18);
    student.print();
}

instanceof 判断 Record 类型

instanceofRecord 一起使用,编译器能够准确的知道 Record 的参数和类型。

例如,判断是否是 Student 类型,然后继续判断年龄是否合法。

public boolean isEligible(Object object) {
    if (object instanceof Student(Integer id, String name, String email, Integer age)) {
        return age >= 18;
    }
    return false;
}

还可以写成下面的方式:

public boolean isEligible(Object object) {
    if (object instanceof Student student) {
        return student.age >= 18;
    }
    return false;
}

最后更新于

这有帮助吗?