Eliminate null pointers, Java 8 gives us a better solution

In normal business development, null pointer is a problem we often encounter.

He may cause our process to fail to proceed normally or some unexpected situations occur.

This is why we need to avoid null pointers, so what are our ways to solve this problem?

Null pointer scenario

  1. Packed type field, because of automatic unboxing a null pointer;
  2. The A object contains the B object. When the field of the B object is obtained through the A object, the method in the B object is directly called without judgment, and a null pointer appears;
  3. String comparison, null.equal("string") has a null pointer
  4. The List returned by the remote is not an empty array but null, and a null pointer appears when operating on it.

How to Troubleshoot Online Null Pointer Problems

In the daily development process, under normal circumstances, we check the log to troubleshoot the problem of null pointers. If the log is not in place, we can only trace the code through the location where NullPointerException is thrown.

This requires us to print the log when writing the code

  • Call the entry of the method to print the input parameters, and the result returned by the method to print the output parameters.
    If the log printing is not done in advance, then we can consider using Ali's Java diagnostic tool Arthas to handle it.
  1. After Arthas starts, get the JVM process
  2. Monitor the input parameters of the method through the watch command

think

For this problem, I have summarized some methods I use in my work,

The most direct operation is to eliminate the possibility of a null pointer from the source, and first judge the null before operating.

Let's take the product information as an example. We want to get the name of his store. How would you write it?

@Data
public class ProductVO implements Serializable {
    
    
    @ApiModelProperty("skuId")
    private Long skuId;
    @ApiModelProperty("商品名称")
    private String name;
    @ApiModelProperty("品牌名")
    private String brandName;
    @ApiModelProperty("库存")
    private Integer quantity;
    @ApiModelProperty("小图列表")
    private List<String> smallImgUrls;
    @ApiModelProperty("店铺信息")
    private ShopVO shop;
  1. Defensive checks, each variable is checked for null, every time you are not sure whether a variable is null, you need to add a nested if block, which increases the number of layers of code.
// 获取店铺名称
private String getShopName1(ProductVO productVO){
    
    
    if (productVO != null){
    
    
        ShopVO shop = productVO.getShopVO();
        if (shop != null){
    
    
            return shop.getName();
        }
    }
    return "";
}
  1. Fast-failure checks, each null check is an exit point, and return a fixed string, but it is unavoidable to forget to check a certain variable.
// 获取店铺名称
private String getShopName2(ProductVO productVO){
    
    
    String result = "";
    if (Objects.isNull(productVO)){
    
    
        return result;
    }
    ShopVO shop = productVO.getShopVO();
    if (Objects.isNull(shop)){
    
    
        return result;
    }
    return shop.getName();
}
  1. Human control, strictly control the data, there can be no non-empty fields, but it is not difficult to ensure that all data are normal data
  2. Use the optional in Java8 to control and model the missing value. When the variable exists, the class is simply encapsulated. When it does not exist, the missing value will be modeled as an empty Optional object.
private static String getName4(ProductVO productVO){
    
    
    return Optional.ofNullable(productVO).flatMap(data -> Optional.ofNullable(shopVO.getShopVO()))
            .map(ShopVO::getName).orElse("");
}
  1. Create an Optional-encapsulated ProductVO object
  2. Convert Optional to Optional
  3. Use map to convert Optional to Optional
  4. Call any method on the chain and return a null, then the result is the default value we set

insert image description here
Among the above methods, we have seen the fourth method, which helps us realize the action of eliminating null pointers with only one line of code, but the Optional in Java 8 needs to combine multiple methods to use it, and now the Internet has There are many detailed method articles, so I won't make too many introductions.

Note the difference between flatMap and Map

For the operation of Stream, flatMap and Map are the methods we often use, and many people don't understand the difference between them.

map() : map applies a function to each element in the list and returns a list of the applied elements.

flatMap() : flatMap is a commonly used combinator, combining mapping [mapping] and flattening [flattening]. flatMap requires a function that takes nested lists and concatenates the results.

For example, you can see the difference at a glance

List<String> list = Arrays.asList("北京 天安门", "上海 东方明珠", "厦门 鼓浪屿"); 
//flatMap方法 
list.stream().flatMap(item -> Arrays.stream(item.split(" "))).collect(Collectors.toList()).forEach(System.out::println);
//结果: 北京 天安门 上海 东方明珠 厦门 鼓浪屿 
// Map方法 
list.stream().map(item -> Stream.of(item.split(" "))).forEach(System.out::println); 
// java.util.stream.ReferencePipeline$Head@6576fe71 
// java.util.stream.ReferencePipeline$Head@76fb509a 
// java.util.stream.ReferencePipeline$Head@300ffa5d

We can see that the difference in their results is very large

The Map method converts the list into a result set of three small List objects

The operation of the FlatMap method is to perform a flattening operation on the basis of the Map method, transform the result into a first-level structure, and take out all the results inside.

practice

List<ProductRespDTO> list = productVOList.getList().stream().map(d -> {
    
    
    return ProductRespDTO.builder().drugEncode(d.getSkuId()).drugName(d.getName())
        .price(BigDecimal.valueOf(d.getPrice()).divide(new BigDecimal("100"))).usage(d.getUseMethod())
        .imgUrl(d.getSmallImgUrls().stream().findFirst().orElse(null)).build();

Will there be a null pointer problem in this example, if it is you, how would you modify it?

Summarize

As for the null pointer problem, it seems that the problem is not big, but it will definitely not work if it affects the normal operation of the online business.

We must have a very clear idea to solve this problem

  1. advance,
  2. Be sure to do a good job of printing the log, in order to troubleshoot problems more conveniently;
  3. When implementing business logic, if you are not very sure about the object you are operating, you must first judge empty and then operate;
  4. For the null pointer of the string type, we can use Objects for comparison;
  5. Input parameter verification of required fields
  6. In the event, since the incident has already happened, we need to quickly locate the problem through the logs and Arthas tools, and quickly repair and go online to reduce the time for the failure to occur:
  7. Afterwards, we can strengthen code review to review our own code to avoid this kind of situation from happening again.

You can share how you usually deal with null pointers~

Guess you like

Origin blog.csdn.net/Park33/article/details/130926288