0

I have a method

public String getSomething(Optional<String> name) {
    StringBuilder something = new StringBuilder("Hello");
    name.ifPresent(n -> something.append(n));
    return something.toString();
}

I use IntelliJ and it complains that you shouldn't use Optionals as parameters and only as return types. I have also read that you want to avoid side-effects in functional programming and you shouldn't manipulate objects.

So what I've been thinking is if it isn't better to do

public String getSomething(String name) {
    StringBuilder something = new StringBuilder("Hello");
    if (name != null) {
        something.append(name);
    }
    return something.toString();
}

Are there any benefits to using Optional? One benefit I can see is that the method tells you that the parameter is an optional one.

uraza
  • 907
  • 4
  • 12
  • 22
  • Why would you want to pass an Optional String? Don't you know that you have a String to pass in the first place? – Murat Karagöz Sep 21 '16 at 14:16
  • Refer to http://stackoverflow.com/questions/31922866/why-should-java-8s-optional-not-be-used-in-arguments – Tunaki Sep 21 '16 at 14:17
  • @MuratK. Sometimes people will call my method without an value on the parameter. String was just as an example, in my real case it is actually a DateRange. And I still want to return a value then. – uraza Sep 21 '16 at 14:18
  • @Tunaki It does answer my first part of the question slightly. But by having Optional I can also use ifPresent, which the other thread doesn't answer. – uraza Sep 21 '16 at 14:20
  • There's also this question http://stackoverflow.com/questions/23454952/uses-for-optional – Tunaki Sep 21 '16 at 14:21
  • The argument passed to `Optional.ifPresent` _has_ to change state. It's fine to have side effects there. – Louis Wasserman Sep 21 '16 at 18:36

3 Answers3

0

Better to pass an Optional than a null. There IntelliJ tries to be too prescriptive. The assumption is, that at the call site you do:

Optional<String> nameOpt = ...
nameOpt.ifPresent(name -> getSomething(name));

Yes, ideal. Hopefully here nameOpt was no parameter...

Here you could use map:

Optional<String> sOpt = nameOpt.map(this::getSomething);

with

public String getSomething(String name) {
    StringBuilder something = new StringBuilder("Hello");
    something.append(name);
    return something.toString();
}

This is perfect functional, and IntelliJ will love it too.

With java 9 the abilities of Optional will grow.


It seems the actual question is: there is a possibly null String parameter, and should we process:

Optional.ofNullableparameter)

further, or pass parameter on.

Also their an Optional map can safely chain processing the possible String and return some other Optional:

// Get the length of the uppercased parameter, when it exists:
Optional<Integer> lengthOpt = Optional.ofNullable(parameter)
    .map(s -> s.toUpperCase(Locale.DE))
    .map(String::length);

If parameter is "Goßlung" - "GOSSLUNG" - Optional.of(8).

(The example should use OptionalInt, but that would be the same.)

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • The caller doesn't necessarily have an Optional. It is more likely the caller will only have the value of the Optional or no value at all. That is why I need to check its presence. – uraza Sep 21 '16 at 14:42
0

Passing Optional is OK in this case, but You could write somethig like

 String nullableName = null;
 Optional<String> name = Optional.ofNullable(nullableName);
 StringBuilder something = new StringBuilder("Hello");
 // getSomething equivalent
 name.map(something::append).orElse(something);

You map not null value or just return builder

Koziołek
  • 2,791
  • 1
  • 28
  • 48
0

The best way to handle this is to tell callers not to pass null in the first place.

This is in fact how most of Java SE works. For instance, if you try to do new URL(null) you will get an exception. The same goes for new BigDecimal(null), System.getProperty(null), ImageIO.read(null), and many others.

Your method should do the same. In fact, there exists a method for that very purpose:

public String getSomething(String name) {
    Objects.requireNonNull(name,
        "This method may not be called with a null argument.");

The calling code should take responsibility for the presence of null values and should avoid calling your method with null. Ideally, the calling code should consider null an abnormal value and should avoid dealing with nulls as much as possible.

VGR
  • 40,506
  • 4
  • 48
  • 63