1. 引言
本文将探讨编程中的"水合"概念,深入解析Java对象水合的具体含义和应用场景。
2. 对象水合
2.1 延迟初始化
延迟加载或延迟初始化是软件应用中的常见模式。在Java中,对象是通过new
关键字创建的类实例。对象是程序的构建块,通过与其他对象交互实现功能。
在面向对象编程中,对象通常代表现实世界实体,因此具有多个关联属性。对象初始化指用实际数据填充对象属性的过程。这通常通过调用类构造函数并传入数据参数完成,也可从网络、数据库或文件系统等数据源进行初始化。
对象初始化有时是资源密集型操作,尤其当数据来自外部数据源时。此外,对象创建后并非总是立即被程序使用。
这种情况下,最佳实践是尽可能延迟对象初始化,直到真正需要时。这种模式称为延迟初始化——我们先创建空数据对象,后续再惰性填充相关数据。有意识地延迟数据初始化能提升代码性能和内存利用率。
创建一个包含多个属性的User
类:
public class User {
private String uId;
private String firstName;
private String lastName;
private String alias;
// 构造函数、getter-setter
}
我们可以创建User
对象并保存在内存中,而不填充其属性:
User iamUser = new User();
2.2 什么是水合?
延迟初始化中,我们刻意延迟已创建对象的初始化过程。向现有空对象填充数据的过程称为水合(Hydration)。
创建的User
实例是空壳对象,因当前不需要而未填充相关数据。要使对象可用,需用领域数据填充,这些数据可来自网络、数据库或文件系统。
通过以下步骤实现用户实例水合。首先编写类级水合方法,使用setter设置数据:
public void generateMyUser() {
this.setAlias("007");
this.setFirstName("James");
this.setLastName("Bond");
this.setuId("JB");
}
现在创建空User
实例,需要时调用generateMyUser()
方法进行水合:
User jamesBond = new User();
// 执行水合
jamesBond.generateMyUser();
通过断言属性状态验证水合结果:
User jamesBond = new User();
Assert.assertNull(jamesBond.getAlias());
jamesBond.generateMyUser();
Assert.assertEquals("007", jamesBond.getAlias());
3. 水合与反序列化
水合和反序列化不是同义词,不可互换使用。**反序列化是从序列化形式重建对象的过程**。我们常存储或通过网络传输对象,此时序列化(对象转字节流)和反序列化(重建对象)就派上用场。
将User
实例序列化到文件:
try {
FileOutputStream fileOut = new FileOutputStream(outputName);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(user);
out.close();
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
需要时从序列化形式重建User
实例:
try {
FileInputStream fileIn = new FileInputStream(serialisedFile);
ObjectInputStream in = new ObjectInputStream(fileIn);
deserializedUser = (User) in.readObject();
in.close();
fileIn.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
⚠️ 关键区别:
- ✅ 反序列化:单步完成对象创建和属性填充
- ✅ 水合:仅向已创建对象添加数据
- ❌ 反序列化 = 对象实例化 + 水合(一步完成)
4. ORM框架中的水合
ORM(对象关系映射)框架结合了面向对象编程与关系数据库。ORM框架实现应用对象与数据库表的映射,使开发者能以原生对象方式操作数据库实体。
对象水合在Hibernate或JPA等ORM框架中更常见。
以JPA实体类Book
及其Repository
为例:
@Entity
@Table(name = "books")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
// 其他列和方法
}
public interface BookRepository extends JpaRepository<Book, Long> {
}
根据ORM原则,实体Book
代表数据库表,实体与数据库的交互通过BookRepository
接口抽象。类实例代表表中的一行。
使用内置find()
方法或自定义查询加载Book
实例时,ORM框架执行以下步骤:
Book aTaleOfTwoCities = bookRepository.findOne(1L);
框架执行流程:
- ✅ 调用默认构造函数初始化空对象
- ✅ 尝试从缓存加载属性数据
- ⚠️ 缓存未命中时,连接数据库查询表
- ✅ 获取
ResultSet
后,水合对象aTaleOfTwoCities
- ✅ 返回最终实例
5. 总结
本文探讨了编程中水合的概念,对比了水合与反序列化的区别,并通过ORM框架和普通对象模型展示了对象水合的实际应用。
本文代码示例可在GitHub获取。