Java 教程
- Java - 首页
- Java - 概述
- Java - 历史
- Java - 特性
- Java vs. C++
- JVM - Java 虚拟机
- Java - JDK vs JRE vs JVM
- Java - Hello World 程序
- Java - 环境搭建
- Java - 基本语法
- Java - 变量类型
- Java - 数据类型
- Java - 类型转换
- Java - Unicode 系统
- Java - 基本运算符
- Java - 注释
- Java - 用户输入
- Java - 日期和时间
Java 控制语句
- Java - 循环控制
- Java - 决策制定
- Java - if-else
- Java - switch
- Java - for 循环
- Java - for-each 循环
- Java - while 循环
- Java - do-while 循环
- Java - break
- Java - continue
面向对象编程
- Java - OOPs 概念
- Java - 对象和类
- Java - 类属性
- Java - 类方法
- Java - 方法
- Java - 变量作用域
- Java - 构造函数
- Java - 访问修饰符
- Java - 继承
- Java - 聚合
- Java - 多态
- Java - 重写
- Java - 方法重载
- Java - 动态绑定
- Java - 静态绑定
- Java - 实例初始化块
- Java - 抽象
- Java - 封装
- Java - 接口
- Java - 包
- Java - 内部类
- Java - 静态类
- Java - 匿名类
- Java - 单例类
- Java - 包装类
- Java - 枚举
- Java - 枚举构造函数
- Java - 枚举字符串
Java 内置类
Java 文件处理
Java 错误和异常
- Java - 异常
- Java - try-catch 块
- Java - try-with-resources
- Java - 多重 catch 块
- Java - 嵌套 try 块
- Java - finally 块
- Java - throw 异常
- Java - 异常传播
- Java - 内置异常
- Java - 自定义异常
Java 多线程
- Java - 多线程
- Java - 线程生命周期
- Java - 创建线程
- Java - 启动线程
- Java - 合并线程
- Java - 线程命名
- Java - 线程调度器
- Java - 线程池
- Java - 主线程
- Java - 线程优先级
- Java - 守护线程
- Java - 线程组
- Java - 关闭钩子
Java 同步
Java 网络编程
- Java - 网络编程
- Java - 套接字编程
- Java - URL 处理
- Java - URL 类
- Java - URLConnection 类
- Java - HttpURLConnection 类
- Java - Socket 类
- Java - 泛型
Java 集合
Java 接口
Java 数据结构
Java 集合算法
高级 Java
- Java - 命令行参数
- Java - Lambda 表达式
- Java - 发送邮件
- Java - Applet 基础
- Java - Javadoc 注释
- Java - 自动装箱和拆箱
- Java - 文件不匹配方法
- Java - REPL (JShell)
- Java - 多版本 Jar 文件
- Java - 私有接口方法
- Java - 内部类菱形运算符
- Java - 多分辨率图像 API
- Java - 集合工厂方法
- Java - 模块系统
- Java - Nashorn JavaScript
- Java - Optional 类
- Java - 方法引用
- Java - 函数式接口
- Java - 默认方法
- Java - Base64 编码解码
- Java - switch 表达式
- Java - Teeing 收集器
- Java - 微基准测试
- Java - 文本块
- Java - 动态 CDS 归档
- Java - Z 垃圾收集器 (ZGC)
- Java - 空指针异常
- Java - 打包工具
- Java - 密封类
- Java - 记录类
- Java - 隐藏类
- Java - 模式匹配
- Java - 简洁的数字格式化
- Java - 垃圾收集
- Java - JIT 编译器
Java 其他
- Java - 递归
- Java - 正则表达式
- Java - 序列化
- Java - 字符串
- Java - Process API改进
- Java - Stream API改进
- Java - 增强的 @Deprecated 注解
- Java - CompletableFuture API改进
- Java - 流
- Java - 日期时间 API
- Java 8 - 新特性
- Java 9 - 新特性
- Java 10 - 新特性
- Java 11 - 新特性
- Java 12 - 新特性
- Java 13 - 新特性
- Java 14 - 新特性
- Java 15 - 新特性
- Java 16 - 新特性
Java APIs 和框架
Java 类引用
- Java - Scanner
- Java - 数组
- Java - 字符串
- Java - Date
- Java - ArrayList
- Java - Vector
- Java - Stack
- Java - PriorityQueue
- Java - LinkedList
- Java - ArrayDeque
- Java - HashMap
- Java - LinkedHashMap
- Java - WeakHashMap
- Java - EnumMap
- Java - TreeMap
- Java - IdentityHashMap
- Java - HashSet
- Java - EnumSet
- Java - LinkedHashSet
- Java - TreeSet
- Java - BitSet
- Java - Dictionary
- Java - Hashtable
- Java - Properties
- Java - Collection
- Java - Array
Java 有用资源
Java - 记录
在 Java 14 中,一个令人兴奋的特性 **record** 作为预览特性被引入。**record** 特性有助于创建不可变数据对象。在 Java 15 版本中,**record 类型** 进行了进一步增强。在 Java 14 和 15 中,为了使用 **record**,必须传递标志 --enable-preview。从 Java 16 开始,不需要此标志,因为 **record** 是 JDK 的标准部分。
Java 记录的目的
Java 记录的主要目的是创建一个数据对象或 POJO,用于在应用程序程序流程中传输数据。在一个多层程序中,领域/模型对象存储从数据源捕获的数据,然后这些模型对象被进一步传递到应用程序/UI 层以处理数据,反之亦然,UI/应用程序将数据存储在数据对象中,然后将这些对象传递给数据层以填充数据源。
由于这些数据对象包含许多字段,开发人员需要编写许多 setter/getter 方法、参数化构造函数、重写的 equals 方法和 hashcode 方法。在这种情况下,record 派上用场,因为它提供了大部分样板代码,开发人员只需关注所需的功能。
Java 记录的特性
以下是使 record 成为一个令人兴奋的特性的一些特性:
- Record 对象具有一个隐式构造函数,所有参数都作为字段变量。
- Record 对象对每个字段变量都有隐式的字段 getter 方法。
- Record 对象对每个字段变量都有隐式的字段 setter 方法。
- Record 对象具有隐式的、合理的 **hashCode()**、**equals()** 和 **toString()** 方法实现。
- 在 Java 15 中,不能在记录中声明本地方法。
- 在 Java 15 中,记录的隐式字段不是 final 的,使用反射修改会抛出 IllegalAccessException。
不使用 Java 记录的示例
让我们创建一个不使用 record 的简单程序,在这个程序中,我们创建了一个 Student 对象并打印其详细信息。Student 具有三个属性:id、name 和 className。为了创建一个学生,我们创建了一个参数化构造函数、setter、getter 方法、equals 和 hashcode 方法。因此,我们的 Student 类包含近 60 多行代码。
package com.tutorialspoint; public class Tester { public static void main(String args[]) { // create student objects Student student1 = new Student(1, "Mahesh", "XII"); Student student2 = new Student(2, "Sudhir", "XII"); // print the students System.out.println(student1); System.out.println(student2); // check if students are same boolean result = student1.equals(student2); System.out.println(result); // check if students are same result = student1.equals(student1); System.out.println(result); // get the hashcode System.out.println(student1.hashCode()); System.out.println(student2.hashCode()); } } class Student{ private int id; private String name; private String className; Student(int id, String name, String className){ this.id = id; this.name = name; this.className = className; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } @Override public String toString() { return "Student[id: " + id + ", name: " + name + ", class: " + className + "]"; } @Override public boolean equals(Object obj) { if(obj == null || !(obj instanceof Student) ) { return false; } Student s = (Student)obj; return this.name.equals(s.name) && this.id == s.id && this.className.equals(s.className); } @Override public int hashCode() { int prime = 19; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((className == null) ? 0 : className.hashCode()); result = prime * result + id; return result; } }
让我们编译并运行上述程序,这将产生以下结果:
Student[id: 1, name: Mahesh, class: XII] Student[id: 2, name: Sudhir, class: XII] false true 371251946 288252156
使用 Java 记录的示例
让我们使用 record 重新创建上述程序,在这个程序中,我们创建一个 Student 对象作为 record 并打印其详细信息。Student 具有三个属性:id、name 和 className。在这里你可以看到区别,完整的 Student 类被一行代码作为 Student record 所取代。
package com.tutorialspoint; public class Tester { public static void main(String args[]) { // create student objects Student student1 = new Student(1, "Mahesh", "XII"); Student student2 = new Student(2, "Sudhir", "XII"); // print the students System.out.println(student1); System.out.println(student2); // check if students are same boolean result = student1.equals(student2); System.out.println(result); // check if students are same result = student1.equals(student1); System.out.println(result); // get the hashcode System.out.println(student1.hashCode()); System.out.println(student2.hashCode()); } } record Student(int id, String name, String className) {}
让我们编译并运行上述程序,这将产生以下结果:
Student[id: 1, name: Mahesh, class: XII] Student[id: 2, name: Sudhir, class: XII] false true 371251946 288252156
我们也可以在记录中添加自定义方法。但通常不需要。
用于密封接口的 Java 记录
由于记录默认情况下是最终的并且可以扩展接口,我们可以定义密封接口并让记录实现它们以更好地管理代码。
示例:密封接口的 Java 记录用法
考虑以下示例:
package com.tutorialspoint; public class Tester { public static void main(String[] args) { Person employee = new Employee(23, "Robert"); System.out.println(employee.id()); System.out.println(employee.name()); } } sealed interface Person permits Employee, Manager { int id(); String name(); } record Employee(int id, String name) implements Person {} record Manager(int id, String name) implements Person {}
让我们编译并运行上述程序,这将产生以下结果:
23 Robert
覆盖 Java 记录的方法
我们可以轻松地覆盖记录方法实现并提供我们自己的实现。
示例:覆盖 Java 记录方法
考虑以下示例:
package com.tutorialspoint; public class Tester { public static void main(String args[]) { // create student objects Student student = new Student(1, "Mahesh", "XII"); System.out.println(student); } } record Student(int id, String name, String className) { public String toString() { return "Id: " + id + ", Name: " + name + ", class: " + className ; } }
让我们编译并运行上述程序,这将产生以下结果:
Id: 1, Name: Mahesh, class: XII