Optional base class used in Java8

Java8 introduced a very interesting Optional class it is to solve the infamous null pointer exception (NullPointerException). When we checked object's properties to determine whether its value to the desired format, only to find not a target we are looking at, but a null pointer, it will immediately throw an annoying NullPointerException exception.

Throwing bricks

Let's look at a simple example:

String address = world.getCountry.getCity.getName;
复制代码

Prior to get the address needs to be checked for each category to prevent null pointer exception:

public String getAddress(World world){
        if (world != null){
            Country country = world.getCountry();
            if (country!=null){
                City city = country.getCity();
                if (city != null){
                    return city.getName();
                }
            }
        }

        return "unknown";
    }
复制代码

You can see how complicated the above checks, the code filled with empty check readability abysmal.

Optional class entry

Variable exists, Optional simply package the class class. When the variable does not exist, the missing value is modeled as a "empty" Optional objects () method returned by Optional.empty. Then you might wonder difference, null and Optional.empty () in which it? Semantically, one thing you can think of them as children, but the real difference between them is very large: if you try to dereference a null, will trigger NullPointerException, but use Optional.empty () is completely all right it is a valid object Optional classes, a variety of scenarios can be called, is very useful.

Optional application of several models

Optional object instance is created

You can create an empty object instance Optional

@Test(expected = NoSuchElementException.class)
    public void createOptionalObject(){
        Optional<String> country = Optional.empty();
        country.get();
    }
复制代码

There is no doubt that when we call the get () method will be reported abnormal NoSuchElementException

Can also create Optioanal Examples include the use of values ​​() and ofNullable () method, except that if the pass in as a parameter of null () will be reported null pointer exception, the presence or absence of an object may be, should be used ofNullable ()

@Test
    public void createOptionalObject(){
        Optional<String> country = Optional.of("中国");
        Optional<String> city = Optional.ofNullable("上海");
        Optional<String> world = Optional.ofNullable(null);
        //下面会报空指针异常
        Optional<String> province = Optional.of(null);
    }
复制代码

How to get the value Optional variables? Optional offers a get () method. But get method when empty Optional encountered objects will throw an exception, so do not use it in the agreed manner, but let us once again into the code caused by a null maintenance nightmare.

Value Optional object access

One way to retrieve the actual value of the object instance is to use the Optional get () method:

@Test
    public void getOptionalObject(){
        String country = "China"
        Optional<String> countryName = Optional.ofNullable(country);
        
        Assert.assertEquals("China",countryName.get());
    }
复制代码

Of course, this method throws an exception if the value is null, to avoid abnormal, we must first check

 @Test
    public void getOptionalObject(){
        City city = new City("ShangHai");
        Optional<City> sample = Optional.ofNullable(city);
        Assert.assertTrue(sample.isPresent());

        Assert.assertEquals(city.getName(),sample.get().getName());
    }
复制代码

Check whether there is value there is another method ifPresent (), which will be passed in addition to checking a Consumer (consumer) parameter, if the object is not empty, it will execute the incoming Lambda expressions

@Test
    public void getOptionalObject(){
        City city = new City("ShangHai");
        Optional<City> sample = Optional.ofNullable(city);
        sample.ifPresent(c -> Assert.assertEquals(city.getName(),sample.get().getName()));
    }
复制代码

If the object is not empty assertion was executed

Return to the default value

Optional provides an API to return the value of the object, or the object returns to the default value is empty

@Test
    public void getOptionalObject(){
        City city = null;
        City city1 = new City("ShangHai");
        City sample = Optional.ofNullable(city).orElse(city1);
        Assert.assertEquals(city1.getName(),sample.getName());
    }
复制代码

The second is the same type of API orElseGet () - behaves slightly differently. This method will return a value when there is the value, if no value, it performs as a parameter a Supplier (provider) interface function, and returns the execution result:

City sample = Optional.ofNullable(city).orElseGet(() -> city1);
复制代码

Abnormal return

Optional also defines orElseThrow () API it will throw an exception when the subject is empty

@Test(expected = IllegalArgumentException.class)
    public void throwOptionalException(){
        City city = null;
        City sample = Optional.ofNullable(city).orElseThrow(() -> new IllegalArgumentException());
    }
复制代码

city ​​is empty it will throw an IllegalArgumentException

This approach gives us a richer semantics, what kind of abnormality may decide to throw, but not always throw NullPointerException.

Examples of actual use Optional

Optional objects extracted from the map using the converted value and

Information extracted from the object is a relatively common pattern, in order to support this model, Optional provides a map method. It works as follows:

@Test
    public void getCityName(){
        City city = new City("ShangHai");
        Optional<City> sample = Optional.ofNullable(city);
        Optional<String> name = sample.map(City::getName);
    }
复制代码

map of the value of the application (call) as a function of the parameter, and then return the value of the package in the Optional in, which makes the return value chain retried operation is made possible, it is not possible to reconstruct the code for it before ?

public Optional<String> getCityName(World world){

        Optional<World> real = Optional.ofNullable(world);
        Optional<String> name =
                real.map(World::getCountry)
                    .map(Country::getCity)
                    .map(City::getName);

        return name;
    }
复制代码

However, this code will not compile, real.map (World :: getCountry) returns an instance Optional this is no problem, but the object is to continue to call back Optional <Optional> type map generated. That you suffered a nested Optional institutions.

optional

Optional two-layer structure of the object

Optional use flatMap link objects

So, how do we solve this problem? Let us recall that you just used in streaming mode: flatMap method. When using a stream, flatMap accepts a function as an argument, a return value of this function is another stream. This method will be applied to each element of flow, eventually forming a new stream flow. But flagMap each stream will be replaced with the newly generated content stream. In other words, each stream generated by the process will be merged into a single flattened or streams. Here you desired result is actually similar, but what you want is two layers of optional combined into one.

public Optional<String> getCityName(World world){

        Optional<World> real = Optional.ofNullable(world);
        Optional<String> name =
                real.flagMap(World::getCountry)
                    .flagMap(Country::getCity)
                    .map(City::getName);

        return name;
    }
复制代码

Use filter excluding certain value

Do you often need to call an object method, then you should first check the object is NULL

public void filterCity(City city){

    Optional<City> real = Optional.ofNullable(city);
    real.filter(c -> c!=null && "ShangHai"
            .equals(c.getName()))
            .ifPresent(x -> System.out.println("ok"));

}
复制代码

summary

  1. null references are introduced to the programming language in history, the purpose is to represent the missing variable values.
  2. Java 8 introduces a new class java.util.Optional, the presence or absence of variable values ​​modeling.
  3. Optional you can create objects using a static factory method Optional.empty, Optional.of and Optional.ofNullable.
  4. Optional class supports a variety of methods, such as map, flatMap, filter, and their corresponding methods Stream class is very similar in concept.
  5. Optional will force you to use more actively Optional dereference objects, in order to deal with the issue of the missing variable values, eventually, you can more effectively prevent the unexpected emergence of the code and to the null pointer exception.
  6. Optional use can help you design a better API, users only need to read the method signature, you will be able to know whether the method accepts a value of type Optional.

Guess you like

Origin juejin.im/post/5d90487fe51d45781420fb5a