Optional Type, An Alternative To Null In Java 8

     Optional type is an alternative to null. null is used to represent the absense of a value. The biggest problem with null is NullPointerException which raises when you refer to a variable that is null. As a result, frequent checks for a null value were necessary to avoid generating an exception. The Optional Type provide a better way to handle such situations. 

Tony Hoare, who invented the concept of null, described it as a " billion dollar mistake".

An object of type Optional can either contain a value of type T or be empty. In other words, an Optional object does not necessarily contain a value. Optional doesn't define any constructors.

Creating Optional Values :

There are several static method for creating Optional values. for example, Optional.of(value) or Optional.empty() are some of them.

creating Optional From Value :
Optional<String> a = Optional.of("a");
The argument to the method of(T a) must not be null.

creating an empty optional :
Optional<String> empOp = Optional.empty();
ofNullable(T value) :

    The ofNullable(value) method returns Optional.of(value) if value is not null and Optional.empty() otherwise. Using ofNullable method you can convert null into Optional. 
 Optional opNull = Optional.ofNullable(null);
Retrieving A Value From Optional :

    The get() method is used to retrieve the value inside the Optional object. it throws NoSuchElementException, in case of no value is present in Optional. The approach to guard a call to get() is by checking whether the value is present or not using isPresent() method.   
if(opt.isPresent()) {
    return opt.get();

Having to call 2 methods to retrieve a value adds overhead to each access. So, a neater approach is to call either ifPresent() or orElse() method. ifPresent method accepts a function. If the optional value exists, it is passed to that function. Otherwise, nothing happens. Instead of using isPresent(), you call
OptionalValue.ifPresent(val -> System.out.println("value inside is " + val)); 
The orElse method which returns an alternative value in case the Optional is empty.
 String str = opt.orElse("No Value");
If creating an alternative value is computationally expensive, the orElseGet() method should be used. This allows you to pass in a supplier that is called only if the optional is genuinely empty.
 String str = opt.orElseGet(() -> "No Value");
If you want to throw an exception if there is no value, use orElseThrow method. pass a constructor reference of the Exception as argument to orElseThrow method.
 String str = empOpt.orElseThrow(NoSuchElementException :: new); 
Using flatMap on Optional Values :

    Suppose you have a method getPerson() that returns an Optional<Person>, and the wrapped Object i.e Person has a method age(), which returns an Optional<Integer>. If they were returning plain objects, you could get the result by calling obj.getPerson().age() . But this composition doesn't work here, since obj.getPerson() has type Optional<Person>, has not Person. Instead call,
Optional<Integer> = obj.gePerson().flatMap(Person::age);
    if obj.getPerson() is present, then the method age() is called on it. other wise an empty Optional<Integer> is returned.
   The other variants of Optional are OptionalDouble, OptionalInt and OptionalLong. These are designed to expressly for use on double, int and long values respectively. As such, they specify the methods getAsDouble(), getAsInt() and getAsLong() respectively, rather than get(). Also, they don't support the filter(), ofNullable(), map() and flatMap() methods.