使用 setter in 或 Else 子句为可选嵌套对象设置默认值

Set default value for optional nested object with setter in orElse clasue

我想检查适配器 class 的值,它是设备 class 中的嵌套对象,如下所示:

@Setter
@Getter
public class Device {
    private Optional<Socket> socket;
}

插座看起来像:

@Setter
@Getter
public class Socket {
    private Optional<Adapter> adapter = Optional.empty();
}

适配器看起来像:

@Setter
@Getter
@AllArgsConstructor
public class Adapter {
    public String name;
}

如果它将为空,请为字段设置默认值 name

我的方法如下:

public static Optional<Adapter> checkAdapterNameOrSetDefaultValue(Optional<Device> device) {
return device
        .flatMap(Device::getSocket)
        .ifPresent(d -> d.getAdapter().orElse(d.setAdapter(Optional.of(new Adapter("DDD")))));
}

看似可行,但 IntelliJ 抱怨 setter 部分无效:

d.setAdapter(Optional.of(new Adapter("DDD")))

留言:

orElse Adapter in Optional cannot be applied to (void)

这里的问题是,在这种情况下是否可以将 void 类型强制转换为 Optional,以便类型相互兼容或以不同的方式设置默认名称。

我注意到这里有几个问题。

  1. 你误用了 Optional,因为有 Optional 个字段。
  2. 您误用了 Optional,将其作为方法参数传递。
  3. checkAdapterNameOrSetDefaultValue 听起来像 void 方法。 checkset 都不意味着返回值。

撇开这些,这里有一个简单的方法来实现它。

public static void checkAdapterNameOrSetDefaultValue(Optional<Device> device) {
    if (device.isPresent()) {
        final Optional<Socket> optionalSocket = device.get().getSocket();
        if (optionalSocket.isPresent()) {
            final Socket socket = optionalSocket.get();
            if (socket.getAdapter().isEmpty()) {
                socket.setAdapter(Optional.of(new Adapter("DDD"));
            }
        }
    }
}

花哨的版本是

device.flatMap(Device::getSocket).ifPresent(socket -> {
    if (socket.getAdapter().isEmpty()) {
        socket.setAdapter(Optional.of(new Adapter("DDD")));
    }
});

is it possible to wrap the result from fancy version to the Adapter class?

是的,但我不支持这样的事情。

public static Optional<Adapter> checkAdapterNameOrSetDefaultValue(Optional<Device> device) {
    final Adapter defaultAdapter = new Adapter("DDD");

    return Optional.of(device
            .flatMap(Device::getSocket)
            .map(d -> {
                if (d.getAdapter().isEmpty()) {
                    d.setAdapter(Optional.of(defaultAdapter));
                    return defaultAdapter;
                }
                return d.getAdapter().get();
            })
            .orElseGet(() -> defaultAdapter));
}