Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

ivan.gavlik
ivan.gavlik

Posted on

     

How to use Optional class (Java) - best practices

Qick info about Optional

Optional isn't meant to be stored as state.

Optional is not meant to be value. It is container for value so that developer can make checking on its value.

Optional is 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.
For example, you probably should never use it for something that returns an array of results, or a list of results; instead return an empty array or list.
You should almost never use it as a field of something or a method parameter.
Also routinely using it as a return value for getters would definitely be over-use.

Following quote from an Oracle article:

It is important to note that the intention of the Optional class is not to replace every single null reference. Instead, its purpose is to help design more-comprehensible APIs so that by just reading the signature of a method, you can tell whether you can expect an optional value. This forces you to actively unwrap an Optional to deal with the absence of a value.

How to surrive from null pointer exceptions

You don't want to get null value or NullPointerException when using Optional

1. Don't assign null to an optional variable

Optional<Person>person=null;
Enter fullscreen modeExit fullscreen mode

Solution: useempty()

Optional<Person>person=Optional.empty();
Enter fullscreen modeExit fullscreen mode

2. Never callget() directly to get the value

Optional<Person>person=PersonService.getPerson();PersonmyPerson=persion.get();
Enter fullscreen modeExit fullscreen mode

Solution: check value withisPresent() before callingget()

Optional<Person>person=PersonService.getPerson();if(person.isPresent()){PersonmyPerson=persion.get();}PersonmyPerson=persion.get();
Enter fullscreen modeExit fullscreen mode

What to return when there is no value present

1. Don't use isPresent()-get() to return default value

if(status.isPresent()){returnstatus.get();}else{return"UNKNOWN";}
Enter fullscreen modeExit fullscreen mode

Solution: useorElse()

returnstatus.orElse("UNKNOWN");
Enter fullscreen modeExit fullscreen mode

2. Don't useorElse() to return computed value

// it is called even if "status" is not emptyreturnstatus.orElse(computeStatus());
Enter fullscreen modeExit fullscreen mode

Solution: useorElseGet()

// computeStatus() is called only if "status" is emptyreturnstatus.orElseGet(this::computeStatus);
Enter fullscreen modeExit fullscreen mode

3. UseorElseThrow() to throw a exception

returnstatus.orElseThrow(Exception::new);
Enter fullscreen modeExit fullscreen mode

How to consume optional values

1. UseifPresent() to consume value orisPresentOrElse() to handle empty case

status.ifPresent(System.out::println);status.isPresentOrElse(System.out::println,()->System.out.println("Status not found"));
Enter fullscreen modeExit fullscreen mode

2. Useor() to return other Optional

returnstatus.or(()->Optional.of("PENDING"));
Enter fullscreen modeExit fullscreen mode

3.orElse()/orElseThrow() goes nicely with streams and lamdbas (don't break a chain)

returnproducts.stream().filter(e->e.getPrice()>200).findFirst().map(Product:getName).orElse("Not found");
Enter fullscreen modeExit fullscreen mode
Optional<Cart>cart=...;Productproduct=...;returncart..filter(e->e.getItems().contains(product)).orElseThrow();
Enter fullscreen modeExit fullscreen mode

Anti-patterns

1. Don't overuse Optional by chaining its methods for purpose of getting value

Statusstatus=...;returnOptional.ofNullable(status).orElse("Pending");
Enter fullscreen modeExit fullscreen mode

Solution

Statusstatus=...;returnstatus!=null?status:"Pending";
Enter fullscreen modeExit fullscreen mode

2. Don't use Optional to return empty Collections or Arrays

Solution: Rely onCollections.emptyList()

returnitems==null?Collections.emptyList():items;
Enter fullscreen modeExit fullscreen mode

3. Don't use Optional as element in Collections or Maps

4. Avoid boxing and unboxing use non-generic Optional

OprionalIntprice==OprionalInt.of(50);OprionalLongprice==OprionalLong.of(50L);
Enter fullscreen modeExit fullscreen mode

5. When designing APIs don't declare filed of type Optional

  • it is not value itself

  • doesn't implement Serializable. It is not intended for use as a property of Java Bean

6. Do not use Optional as constructor or method argument.

Solution: make get method return Optional

classPerson{privatefinalStringname;Person(Stringname){this.name=name;}publicOptional<String>getName(){returnOptional.ofNullable(name);}}
Enter fullscreen modeExit fullscreen mode

Best practices

1. There is no need to Unwrap Optionals for asserting or testing equality

Optional<String>actual=...;Optional<String>expected=...;assertEquals(expected,actual);
Enter fullscreen modeExit fullscreen mode

2. Reject wrapped values using .filter()

returnpassword.filter(p->p.length()>5).isPresent();
Enter fullscreen modeExit fullscreen mode

3.Usemap() orflatMap() to transform value - no need to useisPresent()

// transform name to uper case if null return Optional.empty()returnlowerName.map(String::toUpperCase);
Enter fullscreen modeExit fullscreen mode

3.Usestream() to treat the Optional instance as Stream

List<Prodcut>products=productsId.stream().map(this::fetchProductById).flatMap(Optional::stream).collect(toList());Optional<Product>fetchProductById(Stringid){// implementation}
Enter fullscreen modeExit fullscreen mode

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
arocha profile image
Nefario313
  • Joined

Really helpful tips of using Optional in Java.

CollapseExpand
 
95jai profile image
Jai
  • Joined

It would be a good read if you also provide some rationale behind the statements

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I've been in programing for 8 years, and I'm still surprised at how much of it is just me talking to my computer.
  • Joined

More fromivan.gavlik

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp