21

Is there a good reason why there is no:

OptionalInt.ofNullable(Integer);

It seems to be a perfect fit, if you want to convert an optional/nullable Integer to an OptionalInt. I'm currently using this util method I wrote:

 public static OptionalInt optionalIntOfNullable(Integer integer){
     return integer == null ? OptionalInt.empty() : OptionalInt.of(integer);
 }

what isn't that bad, however, I wonder if I have missed something.

Tim Büthe
  • 62,884
  • 17
  • 92
  • 129

2 Answers2

15

The advantage of OptionalInt over Optional<Integer> is that you can avoid the boxing operation if the source is a primitive int value.

This does not apply if the source is already an Integer. In that case, if your next operation requires an int, an unboxing operation will always occur, either at the time you construct an OptionalInt or when chaining the next operation with an Optional<Integer>. So using an OptionalInt offers no advantage then.

Keep in mind that it is not the intention of these classes to be used as parameter types, so there should be no code expecting an OptionalInt as input. To cite a recent statement from Brian Goetz:

Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result", and using null for such was overwhelmingly likely to cause errors.

(emphasis by me)

Btw., you can convert an Optional<Integer> to an OptionalInt without the conditional operator using the usual operations of Optional:

Integer boxed=null;
OptionalInt optInt=Optional.ofNullable(boxed)
    .map(OptionalInt::of).orElseGet(OptionalInt::empty);

Starting with Java 9, you can also use

OptionalInt optInt=Stream.ofNullable(boxed).mapToInt(Integer::intValue).findAny();

But, as said, it shouldn’t be necessary as normally you simply specify the follow-up operation which will consume either int or Integer, if present. And this works with both, Optional and OptionalInt.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Okay, I get it, makes total sense. Thanks. Can you elaborate on why this should only be used for return types? I mean, you could use it to show a caller that parameters are optional, right? – Tim Büthe Oct 15 '14 at 07:53
  • 3
    There is an easier way to do this: create two overloaded methods, one having the parameter and one without. This is an established pattern in Java since almost twenty years now. These methods may use other methods containing the common code internally. E.g. having `Arrays.sort(Object[])` and `Arrays.sort(T[],Comparator super T>)` is cleaner than `Arrays.sort(T[],Optional>)`, especially for callers not having an `Optional` in the first place. Using `Optional` as parameter type isn’t entirely wrong, but it is not the intended use case, so it won’t drive design decisions. – Holger Oct 15 '14 at 08:07
  • 3
    @David Phillips: when you have many parameters, it’s likely time to rethink the strategy, especially if many of them are optional. I’d resort to a parameter object, the builder pattern, or such alike. – Holger Feb 03 '16 at 10:43
  • Brian Goetz's same statement also says: "You should almost never use it as a field". That's where the disconnect comes up. I use an `Integer` field to represent a possible value (and handle the nullability within my class) but I want to expose that as an `OptionalInt` to consumers of my API. – BrezzaP Apr 05 '18 at 07:53
  • 1
    @BrezzaP when you “handle the nullability within your class”, there shouldn’t be a problem handling the nullability within the method exposing the property as `OptionalInt` as well. So you have well defined responsibilities. – Holger Apr 05 '18 at 09:05
  • So this doesn't make sense because we should just use `Optional` in that case? `public static OptionalInt ofNullable(Integer value) { return value == null ? OptionalInt.empty() : OptionalInt.of(value); }` – Martín Coll May 11 '20 at 19:11
  • 2
    @MartínColl what do you gain from using `OptionalInt` instead of `Optional` in that scenario? As said, it doesn’t avoid boxing, as `Integer` is already boxed. Further, `OptionalInt` lacks several methods of `Optional` (`filter`, `map`, `flatMap`), so you are limiting the functionality for no benefit. – Holger May 12 '20 at 06:29
  • @Holger if you use OptionalInt you pay one box cost, but subsequent code will not perform expensive boxed computations (because the methods to allow it don't exist). If you use Optional you save the one box cost but you have a longer-lived Integer wrapper and also clients may use map, flatMap etc which will be expensive from a boxing perspective. So to me, it seems the choice would depend on context. – Andy Cribbens Jan 10 '21 at 12:42
  • 1
    @AndyCribbens whether you have a longer lived wrapper, depends on what the client code does with the wrapper. And if they want to invoke map, flatMap, etc, there is no advantage in trying to deny them this opportunity. All you'd achieve is having them to box the value again, to be able to do what they want. – Holger Jan 10 '21 at 12:49
  • @Holger yes that makes sense. Although I guess the intention with OptionalInt is that that you would get the value out quickly and operate directly on it with no boxing implications. – Andy Cribbens Jan 10 '21 at 13:29
  • "So using an OptionalInt offers no advantage then." - this is false. OptionalInt is a more compact name, OptionalInt may be included as result type in an interface, for which only one implementation has problem mentioned by @TimBüthe (so other implementations will not have boxing problems). There is also chance that int the future project Valhalla will improve `OptionalInt` more than `Optional`. In other words Optional's only advantage is that OptionalInt is lacking ofNullable (and maybe something like toNullable), other that that it is worse solution compared to OptionalInt. – Sankozi Jul 07 '22 at 09:24
  • 1
    @Sankozi The sentence is “So using an OptionalInt offers no advantage **then**”, clearly referring to this specific scenario. It does not say that OptionalInt had no advantages. There are lots of scenarios, where OptionalInt is useful and preferable. However, this answer is almost a decade old and Valhalla doesn’t seem to be less than yet another decade away. So forgive me for not adding speculations about Valhalla back then. – Holger Jul 07 '22 at 09:31
1

OptionalInt wraps an int, not an Integer value, so the content can be present or not, but can never be null. It's a bit a question of philosophy. As Sotirios Delimanolis has pointed out, if you really require it, just resort to Optional<Integer>.

Ray
  • 3,084
  • 2
  • 19
  • 27
  • 8
    The contents of an `Optional` also can never be `null`. There is no “present but `null`” state for `Optional` instances. – Holger Oct 14 '14 at 15:39