Issue
I want to check the value of an Adapter class which is nested object in Device class which looks like:
@Setter
@Getter
public class Device {
private Optional<Socket> socket;
}
Socket looks like:
@Setter
@Getter
public class Socket {
private Optional<Adapter> adapter = Optional.empty();
}
Adapter looks like:
@Setter
@Getter
@AllArgsConstructor
public class Adapter {
public String name;
}
and in case that it will be empty set a default value for a field name
.
My method looks like:
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")))));
}
Seemingly, it could work but IntelliJ complain about the setter part which is void:
d.setAdapter(Optional.of(new Adapter("DDD")))
with a message:
orElse Adapter in Optional cannot be applied to (void)
Here the question arises whether it is possible to cast the void type on Optional in this case so that the types are compatible with each other or set the default name in a different way.
Solution
I've noticed a couple of problems here.
- You misuse
Optional
by havingOptional
fields. - You misuse
Optional
by passing it as a method argument. checkAdapterNameOrSetDefaultValue
sounds like avoid
method. Neithercheck
norset
implies returning a value.
Leaving these aside, here's a straightforward way to achieve it.
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"));
}
}
}
}
A fancy version would be
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?
Yes, but I am not a supporter of such things.
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));
}
Answered By - Andrew Tobilko
Answer Checked By - Marie Seifert (JavaFixing Admin)