Java Optional详解
Java Optional详解
什么是Optional
Optional是Java 8引入的容器类,用于优雅地处理可能为null的值,避免NullPointerException。
创建Optional
public class OptionalCreation {
public static void main(String[] args) {
// of:非null值
Optional<String> name = Optional.of("Alice");
// ofNullable:可能为null
Optional<String> nullable = Optional.ofNullable(getName());
// empty:空Optional
Optional<String> empty = Optional.empty();
}
private static String getName() {
return Math.random() > 0.5 ? "Bob" : null;
}
}
基本使用
public class OptionalBasic {
public static void main(String[] args) {
Optional<String> name = Optional.of("Alice");
// isPresent:判断是否有值
if (name.isPresent()) {
System.out.println(name.get());
}
// ifPresent:有值时执行操作
name.ifPresent(n -> System.out.println("名字: " + n));
// orElse:提供默认值
String result = name.orElse("Unknown");
// orElseGet:延迟计算默认值
String result2 = name.orElseGet(() -> computeDefault());
// orElseThrow:抛出异常
String result3 = name.orElseThrow(() ->
new RuntimeException("名字不能为空")
);
// stream:转换为流
List<String> list = name.stream().toList();
}
private static String computeDefault() {
System.out.println("计算默认值");
return "Default";
}
}
转换操作
public class OptionalTransform {
public static void main(String[] args) {
Optional<String> name = Optional.of("Alice");
// map:转换值
Optional<Integer> length = name.map(String::length);
System.out.println(length.orElse(0)); // 5
// flatMap:扁平化转换
Optional<String> upper = name.flatMap(n ->
Optional.of(n.toUpperCase())
);
System.out.println(upper.orElse("")); // ALICE
// filter:过滤
Optional<String> filtered = name.filter(n -> n.length() > 3);
System.out.println(filtered.isPresent()); // true
Optional<String> notFiltered = name.filter(n -> n.length() > 10);
System.out.println(notFiltered.isPresent()); // false
}
}
Optional链式操作
public class OptionalChain {
public static void main(String[] args) {
User user = new User("Alice", new Address("北京"));
// 链式获取嵌套值
String city = Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.orElse("未知");
System.out.println(city); // 北京
// 复杂链式操作
String result = Optional.ofNullable(user)
.filter(u -> u.getAge() > 18)
.map(User::getName)
.map(String::toUpperCase)
.orElse("GUEST");
}
}
实际应用场景
方法返回值
public class UserService {
private Map<Integer, User> userMap = new HashMap<>();
// 使用Optional替代null
public Optional<User> findUser(int id) {
return Optional.ofNullable(userMap.get(id));
}
public Optional<String> getUserName(int id) {
return findUser(id)
.map(User::getName);
}
public Optional<String> getUserCity(int id) {
return findUser(id)
.map(User::getAddress)
.map(Address::getCity);
}
}
// 调用
UserService service = new UserService();
String city = service.getUserCity(1)
.orElse("未知城市");
配置管理
public class Config {
private String databaseUrl;
private String cacheUrl;
public Optional<String> getDatabaseUrl() {
return Optional.ofNullable(databaseUrl);
}
public Optional<String> getCacheUrl() {
return Optional.ofNullable(cacheUrl);
}
}
// 使用
Config config = new Config();
String url = config.getDatabaseUrl()
.orElse("jdbc:mysql://localhost:3306/default");
Optional与集合
public class OptionalCollection {
public static <T> List<T> flatten(List<Optional<T>> optionals) {
return optionals.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.toList();
}
public static <T> Optional<T> findFirst(List<T> list, Predicate<T> predicate) {
return list.stream()
.filter(predicate)
.findFirst();
}
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
Optional<Integer> first = findFirst(numbers, n -> n > 3);
first.ifPresent(n -> System.out.println("找到: " + n));
}
}
Optional作为参数
// 不推荐:Optional作为参数
public void process(Optional<String> value) {
value.ifPresent(this::handle);
}
// 推荐:Optional作为返回值
public Optional<String> getValue() {
return Optional.ofNullable(computeValue());
}
常见错误
public class OptionalMistakes {
public static void main(String[] args) {
Optional<String> name = Optional.of("Alice");
// 错误1:直接调用get()前检查isPresent()
if (name.isPresent()) {
System.out.println(name.get()); // 不如直接用ifPresent
}
// 错误2:Optional作为类字段
// private Optional<String> value; // 不推荐
// 错误3:Optional作为方法参数
// public void process(Optional<String> param); // 不推荐
// 正确:链式操作
name.map(String::toUpperCase)
.ifPresent(System.out::println);
// 正确:提供默认值
String result = name.orElse("default");
}
}
Optional性能考虑
public class OptionalPerformance {
// Optional有轻微的内存开销,不要用于频繁创建的场景
// 对于基本类型,使用OptionalInt/OptionalLong/OptionalDouble
public void demo() {
OptionalInt intOpt = OptionalInt.of(42);
OptionalDouble doubleOpt = OptionalDouble.of(3.14);
OptionalLong longOpt = OptionalLong.of(100L);
}
}
总结
Optional是避免NullPointerException的优雅方案。正确使用map、flatMap、orElse等方法,可以让代码更加简洁和安全。记住Optional主要用于方法返回值,不要作为参数或字段使用。