1. 概述
在本教程中,我们将深入探讨Java中的Holder<T>
类。尽管它不是Java的内置类,但Holder<T>
概念可以极大地提高我们的开发效率。让我们了解Holder<T>
的强大之处以及它是如何提升代码的。
2. 值传递语义的局限性
要理解为何我们需要Holder<T>
类,首先考虑一个常见场景:向方法传递一个简单的Boolean
。假设我们有一个模拟服务方法getSupplierByZipCode()
,期望它修改Boolean
值:
public class SupplierService {
public void getSupplierByZipCode(String zip, Boolean result) {
if (zip.startsWith("9")) {
result = true;
} else {
result = false;
}
}
}
现在,我们用一个以“9”开头的zipCode
来测试这个服务,期望result
变为true
:
@Test
public void givenValidZipCode_whenGetSupplierByZipCode_thenTrue() {
SupplierService service = new SupplierService();
Boolean result = false;
String zipCode = "98682";
service.getSupplierByZipCode(zipCode, result);
assertTrue(result);
}
这个测试失败了!由于Java的值传递(/java-pass-by-value-or-pass-by-reference)语义,我们在getSupplierByZipCode()
方法中传递的result
布尔值实际上并未被该方法修改。当方法尝试修改result
时,它只是在操作一个副本,原始的result
保持不变。
这就是Holder<T>
可以帮助我们解决的问题。
3. 设计Holder<T>
的概念
我们可以将Holder<T>
视为一个泛型容器或包装类,能够存储和管理任何类型T
的对象。
它的主要存在是为了克服Java的值传递语义,提供了一种间接的方式来模拟引用传递行为。
这里的T
是一个类型参数,意味着任何有效的Java引用类型都可以替换它。这使得我们只需要一个Holder
类就可以适应任何数据类型。但需要注意的是,并非所有情况下都应随意使用Holder<T>
。特别是处理不可变对象时,使用Holder<T>
可能不是最高效或推荐的方法。
4. Holder<T>
类
假设我们有一个简单的Holder
类,用于封装类型为T
的值。以下是定义它的样子:
public class Holder<T> {
public T value;
public Holder(T value) {
this.value = value;
}
}
在这个例子中,Holder<T>
作为一个容器,用于持有并管理任何类型T
的值。
5. 使用Holder<T>
类
现在,让我们调整SupplierService
,以解决之前Java值传递语义带来的限制。我们不再直接将Boolean
传递给getSupplierByZipCode()
方法,而是使用Holder<T>
类。这样,方法就可以修改Holder
的value
,模拟一种需要从方法返回额外信息的情况,而不仅仅是其返回值。
public class SupplierService {
public void getSupplierByZipCode(String zip, Holder<Boolean> resultHolder) {
if (zip.startsWith("9")) {
resultHolder.value = true;
} else {
resultHolder.value = false;
}
}
}
现在,我们使用修改后的SupplierService
和Holder<T>
重运行测试。
@Test
public void givenValidZipCode_whenGetSupplierByZipCode_thenTrue() {
SupplierService service = new SupplierService();
Holder<Boolean> resultHolder = new Holder<>(false);
String zipCode = "98682";
service.getSupplierByZipCode(zipCode, resultHolder);
assertTrue(resultHolder.value);
}
@Test
public void givenInvalidZipCode_whenGetSupplierByZipCode_thenFalse() {
SupplierService service = new SupplierService();
Holder<Boolean> resultHolder = new Holder<>(true);
String zipCode = "12345";
service.getSupplierByZipCode(zipCode, resultHolder);
assertFalse(resultHolder.value);
}
这次,测试通过了。Holder<T>
类通过提供一层额外的间接性,允许我们在getSupplierByZipCode()
方法中模拟引用传递的特性,从而修改我们想要的变量。
6. 总结
在这篇文章中,我们了解到Holder<T>
类在Java编程中可以作为灵活且强大的工具,应用于各种场景。虽然它不是一个内置类,但Holder<T>
概念为我们提供了创建灵活和可重用代码的方式,能够处理不同类型的对象。这使我们在某些情况下能够克服Java值传递语义的局限性。
如往常一样,这些示例的代码可以在GitHub上找到。