Java programming language is known for its tools and features. It offers a variety of classes, methods and libraries to get the task done but some of these features have also been introduced to cater to some existing issues in Java. One such dreaded issue was Nullpointer exceptions.
Table of Contents
NullPointerException is a runtime exception in Java that occurs when a variable that does not point to any object and refers to null is accessed. As the NullPointerException occurs at runtime, it could not be handled explicitly in an application code. Now, to deal with this exception, Java optional class was introduced in Java 8.
In this article, we will be discussing the Java optional class, The logic behind it, how it works and how you can implement it in your code to prevent null point exceptions at the time of execution.
Java Optional class was primarily designed to handle null point exceptions. The purpose of the Java optional class is to offer a solution for representing optional values in place of null references. Essentially, Java optional class is a wrapper class that contains an optional value, which means that it can either contain an object or it can simply be null. Another major reason behind the popularity of the Java Optional class was that it is also considered a significant move toward functional programming in Java.
Java optional class caters to three possibilities when creating a Java optional object. Those cases are:
– The object will be empty,
– It will certainly have a value,
– It may or may not have a value.
Now, Java optional class offers three methods to deal with these three conditions.
To create an empty Optional object, we simply need to use the empty() static method:
public void usingEmptyMethod() { Optional<String> obj01 = Optional.empty(); assertFalse(empty.isPresent()); }
The isPresent() method used in this example is used to check if the object contains a value or not. We will look at the isPresent() method in the next section.
We can also create an Optional object with the static method of(). This method is used when the object has to contain a value.
See this example below:
public void usingOfMethod() { String str = "hello world"; Optional<String> obj = Optional.of(str); assertTrue(obj.isPresent()); }
It is to be noted that the argument passed to the of() method can never be null. In such a case, it will throw a NullPointerException.
This method is used when you are not certain about whether the object will have a value or not.
If you expect some null values, we can use the ofNullable() method:
public void usingofNullablemethod() { String str = "hello World"; Optional<String> obj = Optional.ofNullable(str); assertTrue(obj.isPresent()); }
By using the nullable method like this, if we pass in a null value, it will not throw an exception instead it will return an empty Optional object just like the empty method.
We can retrieve the actual value inside the Optional object by using the get() method.
It is a simple method that returns the value passed in the optional class object.
See the example below:
public void usingGetMethod() { String str = "hello World"; Optional<String> obj = Optional.ofNullable(str); System.out.print(obj.get()); assertEquals("hello world", obj.get()); }
Here we have printed the value in the object along with confirming it using the assertEquals method. However, if a null argument would have been passed in this method there would be no problem in passing the argument as we have used the ofNullable method but the get() method will still throw an exception.
To avoid such exceptions, we can choose to first verify if the object contains a value or not. It can be done by either using the ispresent() method or ifpresent() method.
As used in earlier examples isPresent() is a Boolean method used to check whether the object contains a value or not.
See the example below where the isPresent() method is used:
public void usingIsPresentMethod() { String str = "hello World"; Optional<String> obj = Optional.ofNullable(str); assertTrue(obj.isPresent()); assertEquals(user.getEmail(), opt.get().getEmail()); }
Another option for checking the presence of a value in the object is by using the ifPresent() method. In addition to performing the check, this method also takes a Consumer argument and executes a lambda expression if the object contains a value.
obj.ifPresent( u -> assertEquals(str));
this assertion will only be executed if the user object is not null.
The Java Optional class offers two methods that can be used to return the value of the object or a default value in the case of an empty object.
This method works in a very simple way. It returns the value if it is present in the object and if contains null, it returns the argument it receives.
public void usingOrElseMethod() { String str1 = null; String str2 = “Hello World”; String result = Optional.ofNullable(str1).orElse(str2); assertEquals(str2, result); }
Here, the str1 was null, so the str2 will be returned automatically as a default.
If the initial value of the object would not be not null, then the default value will be ignored.
See this code below:
public void usingOrElseMethod() { String str1 = “Hello World”; String str2 = “Optional class in Java”; String result = Optional.ofNullable(str1).orElse(str2); assertEquals("Hello World", result); }
This will return the string in str1 as it is not null and str2 will be ignored.
This second method has a slightly different property. In this case, the orElseGet() returns the value if it is present, otherwise, it executes the Supplier functional interface that is received as an argument which is then invoked and the value of the invocation will be returned:
public void usingOrElseGetMethod() { String nullStr = null; String result = Optional.ofNullable(nullStr).orElseGet(() -> "Hello World"); assertEquals("Hello World", result); }
OrElse() and orElseGet() methods can be used to return a value but Java Optional class also defines an orElseThrow() method which instead of returning an alternate value, throws a selected exception in case of a null object,
(expected = IllegalArgumentException.class) public void usingOrElseThrow() { String str = “”; String result = Optional.ofNullable(str) .orElseThrow( () -> new IllegalArgumentException()); }
Here, if the string is null, an IllegalArgumentException will be thrown. Despite throwing an exception, this method can be very useful as it let you decide the exception that gets thrown instead of always throwing the infamous NullPointerException.
So far, we have covered the basic working of the optional class and its functions. Now, we will be looking at two additional methods that can be used to transform Optional values
The map() method applies the Function argument to the object value. It then returns the result wrapped in an Optional. This transformation later makes it possible to apply and chain further operations on the returned value.
See the example below where the map method is used to further chain the orElse() method:
public void usingMapMethod() { String str = “Hello World”; String result = Optional.ofNullable(str) .map(x -> str).orElse("This is defult value."); assertEquals(result, str); }
The flatMap() method also transforms the object value but the difference here is that the map method transforms the values only when they are unwrapped whereas the flatMap method takes a wrapped value, unwraps it and then transforms it. The flatmap() method takes a Function argument just as the map() method but it is then applied to an Optional value and the result is then directly returned.
See this example where the Student class has a method that returns an Optional:
public class Student { private String name; public Optional<String> getName() { return Optional.ofNullable(name); } ... ... ... }
Since the getName method returns an optional with the String value, you can use it as an argument for the flatMap(). The method will then directly return the unwrapped String value,
public void usingFlatMapMethod() { Student std01 = new User("Shaharyar Malik Lalani"); String name = Optional.ofNullable(std01) .flatMap(s -> s.getName()).orElse("Not mentioned"); assertEquals(name, user.getName().get()); }
Along with transformation, the Java Optional class also offers methods to filter the values based on certain conditions.
A Predicate is passed as an argument in the filter() method and it returns the value as it is originally only if the test evaluates to true. Or else, the returned value would be an empty Optional. It can be used for the verification of an object value.
See this ID verification example:
public void usingFilterMethod() { String myId = “CS-1323”; Optional<String> result = Optional.ofNullable(myId) .filter(s -> myId != null && myId.contains("CS-")); assertTrue(result.isPresent()); }
In this article, we have covered some of the most important features of the Java 8 Optional class. We explored the primary problem that this class solves. We also learned about how to get the value of an Optional object and how to return it using the get(), orElse() and orElseGet() methods. Lastly, we also looked into some methods to transform and filter the Java optional values.
Also Read: Optional Parameters In Java: Common Strategies and Approaches
Full Stack Java Developer | Writer | Recruiter, bridging the gap between exceptional talent and opportunities, for some of the biggest Fortune 500 companies.
Create a free profile and find your next great opportunity.
Sign up and find a perfect match for your team.
Xperti vets skilled professionals with its unique talent-matching process.
Connect and engage with technology enthusiasts.
© Xperti.io All Rights Reserved
Privacy
Terms of use