为了更深入展示 Optional
的 API,这次我们会涉及更多的 Optional
方法,比如 map()
、flatMap()
、orElse()
、orElseGet()
和 orElseThrow()
。我们继续使用之前的 User
和 email
场景,并引入更多的处理方式。
示例场景扩展:
在这次的示例中,我们会进一步扩展场景,比如:
- 将
User
对象与Address
对象结合,演示Optional
嵌套和flatMap()
的使用。 - 展示各种
Optional
的 API,比如默认值、异常抛出等情况。
使用 Optional
之前的代码:
public class Address {
private String street;
public Address(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
}
public class User {
private String email;
private Address address;
public User(String email, Address address) {
this.email = email;
this.address = address;
}
public String getEmail() {
return email;
}
public Address getAddress() {
return address;
}
}
public class Main {
public static void main(String[] args) {
Address address = new Address("123 Main St");
User userWithEmailAndAddress = new User("user@example.com", address);
User userWithoutEmail = new User(null, null);
printUserEmail(userWithEmailAndAddress);
printUserEmail(userWithoutEmail);
printUserAddress(userWithEmailAndAddress);
printUserAddress(userWithoutEmail);
}
public static void printUserEmail(User user) {
if (user != null && user.getEmail() != null) {
System.out.println("User's email is: " + user.getEmail());
} else {
System.out.println("User's email is not available.");
}
}
public static void printUserAddress(User user) {
if (user != null && user.getAddress() != null) {
System.out.println("User's address is: " + user.getAddress().getStreet());
} else {
System.out.println("User's address is not available.");
}
}
}
使用 Optional
之后的代码:
我们使用 Optional
包装 email
和 address
,并展示各种 Optional
的方法。
import java.util.Optional;
public class Address {
private String street;
public Address(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
}
public class User {
private Optional<String> email;
private Optional<Address> address;
public User(String email, Address address) {
// 使用 Optional 包装 email 和 address
this.email = Optional.ofNullable(email);
this.address = Optional.ofNullable(address);
}
public Optional<String> getEmail() {
return email;
}
public Optional<Address> getAddress() {
return address;
}
}
public class Main {
public static void main(String[] args) {
Address address = new Address("123 Main St");
User userWithEmailAndAddress = new User("user@example.com", address);
User userWithoutEmail = new User(null, null);
// 演示 Optional 的各种方法
printUserEmail(userWithEmailAndAddress);
printUserEmail(userWithoutEmail);
printUserAddress(userWithEmailAndAddress);
printUserAddress(userWithoutEmail);
// 进一步展示 Optional 的其他操作
demonstrateOptionalAPIs(userWithEmailAndAddress);
demonstrateOptionalAPIs(userWithoutEmail);
}
public static void printUserEmail(User user) {
// 使用 ifPresentOrElse 打印 email 或缺省值
user.getEmail().ifPresentOrElse(
email -> System.out.println("User's email is: " + email),
() -> System.out.println("User's email is not available.")
);
}
public static void printUserAddress(User user) {
// 使用 flatMap 处理嵌套的 Optional
String street = user.getAddress()
.flatMap(Address::getStreet) // 展开嵌套的 Optional
.orElse("Address is not available.");
System.out.println("User's address: " + street);
}
public static void demonstrateOptionalAPIs(User user) {
// 使用 map 操作 email 并将其转为大写
String upperCaseEmail = user.getEmail()
.map(String::toUpperCase) // 转换为大写
.orElse("DEFAULT@EMAIL.COM");
System.out.println("Uppercase email: " + upperCaseEmail);
// 使用 orElse 提供默认值
String email = user.getEmail().orElse("default@example.com");
System.out.println("Email: " + email);
// 使用 orElseGet 提供通过 Lambda 计算的默认值
String emailWithSupplier = user.getEmail().orElseGet(() -> "supplier@example.com");
System.out.println("Email with supplier: " + emailWithSupplier);
// 使用 orElseThrow 在没有值时抛出异常
try {
String mustHaveEmail = user.getEmail().orElseThrow(() -> new IllegalArgumentException("Email is required!"));
System.out.println("Email: " + mustHaveEmail);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
详细讲解 Optional
API 的变化:
-
ifPresentOrElse()
:- 之前:我们需要手动进行
null
检查。 - 之后:使用
Optional.ifPresentOrElse()
,可以简化逻辑,并直接在Optional
存在值或不存在值时执行不同的操作。
- 之前:我们需要手动进行
-
map()
:- 之前:我们需要对获取的值进行检查,然后手动转换。
- 之后:通过
Optional.map()
,我们可以在值存在时对其进行转换操作,而无需显式检查null
。
-
flatMap()
:- 之前:嵌套的
Optional
需要层层检查。 - 之后:使用
flatMap()
,可以避免嵌套Optional
,直接对内部值进行操作。
- 之前:嵌套的
-
orElse()
:- 之前:手动为
null
值提供默认值。 - 之后:
Optional.orElse()
允许我们提供默认值,如果值为null
,则返回默认值。
- 之前:手动为
-
orElseGet()
:- 区别:与
orElse()
类似,但orElseGet()
接收一个Supplier
(函数式接口),当值不存在时,Supplier
会被执行来生成默认值,这在需要计算默认值的情况下更加高效。
- 区别:与
-
orElseThrow()
:- 之前:如果值不存在,需要手动抛出异常。
- 之后:使用
Optional.orElseThrow()
,我们可以在值为null
时自动抛出指定的异常。
总结:
使用 Optional
后,代码不但更加简洁,还能通过函数式编程的方式进行操作,减少显式的 null
检查。此外,Optional
提供了丰富的 API,可以处理不同的情况,如提供默认值、抛出异常、转换值等。通过这些 API 的合理使用,能够显著提高代码的健壮性和可读性。