- 通常创建后内容不改变的对象很有用,可阅读Immutable Objects in Java了解构建此类类的完整描述。
- 以构建
PersonClass
为例,要创建不可变实例,此类需:有初始化字段的构造函数、将字段设为private
和final
以确保构造函数设置后不可更改、提供获取字段的方法、不可扩展并标记为final
、重写equals
、hashCode
和toString
方法。 在 Java 16 之前构建此类需 40 行代码,如下:
package com.davidemarino; import java.util.Objects; public final class PersonClass { private final String firstName; private final String lastName; public PersonClass(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } @Override public boolean equals(Object o) { if (o == null || getClass()!= o.getClass()) return false; PersonClass that = (PersonClass) o; return Objects.equals(firstName, that.firstName) && Objects.equals(lastName, that.lastName); } @Override public int hashCode() { return Objects.hash(firstName, lastName); } @Override public String toString() { return "PersonClass{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + '}'; } }
可按如下使用:
package com.davidemarino; public class Main { public static void main(String[] args) { PersonClass personClass = new PersonClass("John", "Doe"); System.out.println("First name: " + personClass.getFirstName()); System.out.println("Last name: " + personClass.getLastName()); System.out.println(personClass); } }
Java 16 后可使用
record
关键字定义此类类,如下:package com.davidemarino; public record PersonRecord(String firstName, String lastName) { }
使用方式如下:
package com.davidemarino; public class Main { public static void main(String[] args) { PersonClass personClass = new PersonClass("John", "Doe"); System.out.println("First name: " + personClass.getFirstName()); System.out.println("Last name: " + personClass.getLastName()); System.out.println(personClass); PersonRecord personRecord = new PersonRecord("John", "Doe"); System.out.println("First name: " + personRecord.firstName()); System.out.println("Last name: " + personRecord.lastName()); System.out.println(personRecord); } }
区别在于获取方法的命名约定不同,传统方式为
getFirstName()
和getLastName()
,record
方式为firstName()
和lastName()
。若有可变对象字段,如在
PersonClass
中添加List<String> preferences
字段,传统方式需在构造函数和获取方法中创建字段副本,如下:package com.davidemarino; import java.util.ArrayList; import java.util.List; import java.util.Objects; public class PersonClass { private final String firstName; private final String lastName; private final List<String> preferences; public PersonClass(String firstName, String lastName, List<String> preferences) { this.firstName = firstName; this.lastName = lastName; this.preferences = new ArrayList<>(preferences); } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public List<String> getPreferences() { return new ArrayList<>(preferences); } @Override public boolean equals(Object o) { if (o == null || getClass()!= o.getClass()) return false; PersonClass that = (PersonClass) o; return Objects.equals(firstName, that.firstName) && Objects.equals(lastName, that.lastName) && Objects.equals(preferences, that.preferences); } @Override public int hashCode() { return Objects.hash(firstName, lastName, preferences); } @Override public String toString() { return "PersonClass{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", preferences=" + preferences + '}'; } }
使用
record
方式如下:package com.davidemarino; import java.util.ArrayList; import java.util.List; public record PersonRecord(String firstName, String lastName, List<String> preferences) { public PersonRecord { preferences = new ArrayList<>(preferences); } public List<String> preferences() { return new ArrayList<>(preferences); }
此部分代码称为紧凑规范构造函数,相当于以下标准构造函数:
public PersonRecord(String firstName, String lastName, List<String> preferences) { preferences = new ArrayList<>(preferences); this.firstName = firstName; this.lastName = lastName; this.preferences = preferences; }
- 结论:传统创建 Java 不可变对象需大量样板代码,Java 16 引入
record
后,开发者有简洁且表达力强的方式定义不可变数据结构,自动生成构造函数、封装字段并重写equals
等方法,减少手动编码工作量,使代码更易读、维护且不易出错,是 Java 类型系统的强大补充,简化了健壮不可变数据模型的创建。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。