[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