Oscar Funes

Published on

Refactoring Java Optional

Java Optional’s imperative checks, by usage of .isPresent() and .get() where a good gateway into using that container for avoiding Null Pointer Exceptions.

I like refactoring code and also dislike imperative checks for the Optional type. So I decided to grab 4 examples from relatively old code that migrated to Java 8 and Optionals.

There’s also the Guava’s Optional type, which offers more or less the same methods to work with Optionals.

The reason why I think using .isPresent() is not as good, is because most of the times there’s no real advantage of using that method over != null.

We can also avoid using If syntax and making code less imperative and moving towards a more declarative approach.

Declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow.

I think Java Optionals are a way to change how we think about Java imperative coding, together with Lambdas they can make the syntax terser.

Let’s get on with the examples. All these examples I extracted from code lying around in the different Java repositories at work; which I changed the names of variables, functions, et al., for reasons.

Example 1

private boolean isValidResource(final String resourceId, final boolean flag) {
  final Optional<Resource> resourceOptional = serviceAClient.getResourceByID(resourceId, flag);
  if (resourceOptional.isPresent()) {
    final String propertyA = resourceOptional.get().getPropertyA();
    return ("ValueA".equals(propertyA) || ("ValueB".equals(propertyA) && flag));
  }
  return false;
}

In this example, there a call to an external service to obtain a single resource, and from the Optional resource, we need to access a property. If the resource or the property is not present, return false;

We can enhance this example by the use of .map() because accessing the property would be guarded by the optional check on the property.

private boolean isValidResource(final String resourceId, final boolean flag) {
  return serviceAClient.getResourceByID(resourceId, flag)
    .map(resource -> resource.getPropertyA())
    .map(propertyA -> ("ValueA".equals(propertyA) || ("ValueB".equals(propertyA) && flag)))
    .orElse(false);
}

Example 2

public String getAccessToken() {
  final Optional<String> accessTokenOptional = authService.getAccessToken();
  return accessTokenOptional.isPresent() ? accessTokenOptional.get() : null;
}

In this second example, there’s no real advantage to using an optional over a simple != Null check. We could avoid the ternary operator by using the method .orElse(null) Which I think would make the code less verbose. Alternatively, we can add a second check to even guard against empty strings with a .filter() that way we only return a string with a value or null.

public String getAccessToken() {
   return authService.getAccessToken()
    .filter(token -> StringUtils.hasText(token))
    .orElse(null);
}

Example 3

public long getCurrentUserId() {
  final Optional<Long> userIdOptional = new UserService().getUserId();
  if (!userIdOptional.isPresent()) {
    throw new NoCredentialsException("User id not found");
  }
  return userIdOptional.get();
}

This example, while seemingly trivial can be made in a more declarative style by using the .orElseThrow() method from the Optional resource.

This will effectively remove the If statement, making the overall function more terse.

public long getCurrentUserId() {
  return new UserService().getUserId()
    .orElseThrow(() -> new AuthenticationCredentialsNotFoundException("User id not found"));
}

Example 4

private void doSomeSideEffect(final StateToSet stateToSet, final Double amount, final String stringA, final String stringB, final EnumValue enumValue) {
  final ResourceA resourceA = new ResourceA.ResourceABuilder()
    .withPropA(amount)
    .withPropAEnumValue(ENUM_VALUE_A)
    .withPropAFlag(true)
    .withPropB(stringA)
    .withPropC(stringB)
    .build();

  final Optional<ResourceB> resourceBOptional = serviceC.getResourceB(serviceC.getSomethingFromResourceA(resourceA), enumValue.name(), ValueC.name());
  if (resourceBOptional.isPresent()) {
      final ResourceB resourceB = resourceBOptional.get();
      stateToSet.setReceiveAmount(resourceB.getPropertyD().getValue());
  }
}

This example is a weird one due to the nature of only doing side effects in the function. It’s a void method that only does a call to an external service and based on the response does another external service call and based on that response, if it’s present performs another side effect.

Even then, Optional’s provide help in this case through the method ifPresent(), and .map() for guarding us against problem when the property or value are not present.

private void doSomeSideEffect(final StateToSet stateToSet, final Double amount, final String stringA, final String stringB, final EnumValue enumValue) {
  final ResourceA resourceA = new ResourceA.ResourceABuilder()
    .withPropA(amount)
    .withPropAEnumValue(ENUM_VALUE_A)
    .withPropAFlag(true)
    .withPropB(stringA)
    .withPropC(stringB)
    .build();

  serviceC.getResourceB(serviceC.getSomethingFromResourceA(resourceA), enumValue.name(), ValueC.name())
    .map(resourceB -> resourceB.getPropertyD())
    .map(propertyD -> propertyD.getValue())
    .ifPresent(value -> stateToSet.setPropertyDValue(value));
}

Conclusion

I don’t know the actual value of doing more declarative usage of Optionals versus imperative checks besides my assessment of readability, and easier to grasp semantic. The value is specific to your team, and knowledge of the language.

In the end, I just wanted to express that Optionals are meant to be a way to allow for more declarative code in Java. We should look to work in such a way with them.

Happy coding!