[elegant code] 03 optional null pointer exception

[elegant code] 03 optional null pointer exception

Welcome to b station official account / public number [hexagon warrior Xia Ning], a man who wants to fill all the indicators. The article has been published in github directory Included.
The handsome and beautiful in front of the screen, if it helps you, please like it and add a collection, which is really important to me. Don't worry about where you go next time.

1. Background introduction

NPE problems will always be encountered in daily development, but java provides options, which allows us to write code smoothly and avoid NPE

2. Establish the hierarchy of Child, Parent and GrandParent

Create a class grandparent - > parent - > list with the following structure

  • Child
@Data
@AllArgsConstructor
@ToString(callSuper = true)
@NoArgsConstructor
@Accessors(chain = true)
public class Child {
    private List<String> list;
    private String str;
}
  • GrandParent
@Data
@AllArgsConstructor
@ToString(callSuper = true)
@NoArgsConstructor
@Accessors(chain = true)
public class GrandParent {
    private Parent parent;
}
  • Parent
@Data
@AllArgsConstructor
@ToString(callSuper = true)
@NoArgsConstructor
@Accessors(chain = true)
public class Parent {
    private Child child;
}

  • Test class
GrandParent opt1 = null;
// Get the bottom data. At this time, the topmost layer is null, and NPE will not be reported
String opt1Str = Optional.ofNullable(opt1).map(o1 -> o1.getParent())
                .map(o2 -> o2.getChild()).map(l -> l.getStr()).orElse(null);
System.out.println(String.format("%s:%s", "opt1Object", opt1Str));

// Get the lowest level data. At this time, the second layer is null and will not report NPE
GrandParent opt2 = null;
List<String> opt2list = Optional.ofNullable(opt2).map(o1 -> o1.getParent())
                .map(o2 -> o2.getChild()).map(l -> l.getList()).orElse(null);
System.out.println(String.format("%s:%s", "opt2list", opt2list));

// Get the lowest level data. At this time, all data is complete, and there is no problem with either list or string
GrandParent opt3 = new GrandParent().setParent(new Parent().setChild(new Child().setStr("ssss").setList(Stream.of("1", "2").collect(Collectors.toList()))));
List<String> opt3list = Optional.ofNullable(opt3).map(o1 -> o1.getParent())
                .map(o2 -> o2.getChild()).map(l -> l.getList()).orElse(null);
String opt3Str = Optional.ofNullable(opt3).map(o1 -> o1.getParent())
                .map(o2 -> o2.getChild()).map(l -> l.getStr()).orElse(null);
System.out.println(String.format("%s:%s", "opt3list", opt3list));
System.out.println(String.format("%s:%s", "opt3Str", opt3Str));
  • Output results
opt1Object:null
opt2list:null
opt3list:[1, 2]
opt3Str:ssss

It can be found that for nested classes, whether string or list, if any of the middle classes is null, it will directly return null instead of multi-level nesting if

3. Very complex optional usage

Of course, there are always some strange results. For example, querying the database will return a list < map < string, string > > structure, which can also be done with Optinoal

// Get the list embedded map and randomly return a key. At this time, the NPE will not be obtained if the list is null
List<Map<String, String>> listR = null;
String result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())
        .flatMap(l -> l.keySet().stream().findAny()).orElse(null);
System.out.println(result);

// Get the list embedded map and randomly return a key. At this time, the list without elements will not be NPE
listR = new ArrayList<Map<String, String>>();
result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())
        .flatMap(l -> l.keySet().stream().findAny()).orElse(null);
System.out.println(result);

// Obtain the list embedded map and randomly return a key. At this time, there is a HashMap, but the acquisition of HashMap without elements will not NPE
listR = new ArrayList<Map<String, String>>() {{
    add(new HashMap<String, String>());
}};
result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())
        .flatMap(l -> l.keySet().stream().findAny()).orElse(null);
System.out.println(result);

// Get the list map and return a key randomly. At this time, all structures are complete
listR = new ArrayList<Map<String, String>>() {{
    add(new HashMap<String, String>() {{
        put("C", "0");
    }});
}};
result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())
        .flatMap(l -> l.keySet().stream().findAny()).orElse(null);
System.out.println(result);

The output results are as follows:

null
null
null
C

4. Other excellent methods to eliminate null pointer exceptions

The first is @ NonNull of lombok, which can be used on method parameters. If NULL is passed in, the exception will be thrown directly, and the exception location and condition will be accurately printed in the log. It is very suitable for verifying parameters and increasing code simplicity. You can see the verification method of non null pointers Elegant and front-end interaction

Of course, the class just written returns null, but it doesn't matter. You can use the following tool classes to throw custom exceptions or return directly under various circumstances

 // The blank judgment of general objects will not be NPE
System.out.println(String.format("%s:%s", "StringUtils", StringUtils.isBlank(null)));
System.out.println(String.format("%s:%s", "defaultIfNull", ObjectUtils.defaultIfNull(null, "defaultIfNull")));
List list = null;
Map map = null;
Set set = null;
String[] arr = null;
// The blank judgment of conventional collection will not be NPE
System.out.println(String.format("%s:%s", "list", CollectionUtils.isEmpty(list)));
System.out.println(String.format("%s:%s", "map", CollectionUtils.isEmpty(map)));
System.out.println(String.format("%s:%s", "set", CollectionUtils.isEmpty(set)));
System.out.println(String.format("%s:%s", "arr", ArrayUtils.isEmpty(arr)));

The output results are as follows:

StringUtils:true
defaultIfNull:defaultIfNull
list:true
map:true
set:true
arr:true

Keywords: Java Programming jvm Back-end

Added by shantred on Mon, 03 Jan 2022 11:46:58 +0200