null ポインタを排除し、Java 8 がより良いソリューションを提供します

通常のビジネス開発では、NULL ポインターはよく遭遇する問題です。

彼は私たちのプロセスを正常に進められなかったり、予期せぬ状況が発生したりする可能性があります。

これが、null ポインターを避ける必要がある理由です。この問題を解決するにはどのような方法があるでしょうか?

Null ポインターのシナリオ

  1. NULL ポインタが自動的にアンボックス化されるため、パック型フィールド。
  2. A オブジェクトには B オブジェクトが含まれており、A オブジェクトを通じて B オブジェクトのフィールドを取得すると、B オブジェクト内のメソッドが判断せずに直接呼び出され、null ポインタが表示されます。
  3. 文字列比較、null.equal("string") には null ポインタがあります
  4. リモートから返される List は空の配列ではなく null であり、操作すると null ポインタが表示されます。

オンラインの Null ポインターの問題をトラブルシューティングする方法

日々の開発プロセスでは、通常、Null ポインターの問題をトラブルシューティングするためにログを確認しますが、ログが存在しない場合は、NullPointerException がスローされた場所からコードを追跡することしかできません。

これには、コードを記述するときにログを出力する必要があります。

  • メソッドのエントリを呼び出して入力パラメータを出力し、メソッドによって返された結果を呼び出して出力パラメータを出力します。
    ログ出力が事前に行われていない場合は、Ali の Java 診断ツール Arthas を使用して処理することを検討できます。
  1. Arthas が起動したら、JVM プロセスを取得します
  2. watch コマンドを使用してメソッドの入力パラメータを監視します。

考え

この問題に対して、私が仕事で使用しているいくつかの方法をまとめました。

最も直接的な操作は、ソースから null ポインターの可能性を排除し、最初に null を判断してから操作することです。

商品情報を例に挙げると、彼のお店の名前を知りたいのですが、どのように書きますか?

@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. 防御チェックでは、各変数が null かどうかチェックされます。変数が null かどうか不明な場合は常に、ネストされた if ブロックを追加する必要があり、コードのレイヤー数が増加します。
// 获取店铺名称
private String getShopName1(ProductVO productVO){
    
    
    if (productVO != null){
    
    
        ShopVO shop = productVO.getShopVO();
        if (shop != null){
    
    
            return shop.getName();
        }
    }
    return "";
}
  1. 高速障害チェックでは、各 null チェックが出口点となり、固定文字列を返しますが、特定の変数のチェックを忘れるのは避けられません。
// 获取店铺名称
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. 人間による管理、データの厳密な管理、空でないフィールドは存在できませんが、すべてのデータが正常なデータであることを確認することは難しくありません
  2. Java8 のオプションを使用して欠損値を制御およびモデル化します。変数が存在する場合、クラスは単純にカプセル化されます。変数が存在しない場合、欠損値は空の Optional オブジェクトとしてモデル化されます。
private static String getName4(ProductVO productVO){
    
    
    return Optional.ofNullable(productVO).flatMap(data -> Optional.ofNullable(shopVO.getShopVO()))
            .map(ShopVO::getName).orElse("");
}
  1. オプションでカプセル化された ProductVO オブジェクトを作成する
  2. オプションをオプションに変換
  3. マップを使用してオプションをオプションに変換します
  4. チェーン上の任意のメソッドを呼び出して null を返すと、結果は設定したデフォルト値になります。

ここに画像の説明を挿入
上記のいくつかのメソッドのうち、4 番目のメソッドは、たった 1 行のコードで null ポインタを削除するアクションを実現するのに役立ちますが、Java 8 の Optional を使用するには複数のメソッドを組み合わせる必要があり、現在はそれが利用可能です。詳しい方法の記事はたくさんあるので、あまり紹介はしません。

flatMap と Map の違いに注意してください

Stream の操作には flatMap と Map がよく使われますが、両者の違いが分からない人も多いです。

map() :map はリスト内の各要素に関数を適用し、適用された要素のリストを返します。

flatMap() : flatMap は、マッピング [マッピング] とフラット化 [フラット化] を組み合わせる、一般的に使用されるコンビネータです。flatMap には、ネストされたリストを取得し、結果を連結する関数が必要です。

たとえば、一目で違いがわかります

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

結果の差が非常に大きいことがわかります

Map メソッドは、リストを 3 つの小さな List オブジェクトの結果セットに変換します。

FlatMap メソッドの操作は、Map メソッドに基づいて平坦化操作を実行し、結果を第 1 レベルの構造に変換し、内部の結果をすべて取り出すことです。

練習

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();

この例では Null ポインターの問題が発生しますか。あなたなら、どのように変更しますか?

要約する

Null ポインタの問題に関しては、大きな問題ではないようですが、オンライン ビジネスの通常の運営に影響を与えるようでは間違いなく問題になります。

この問題を解決するには非常に明確なアイデアが必要です

  1. 事前,
  2. 問題のトラブルシューティングをより簡単に行うために、ログを適切に出力してください。
  3. ビジネス ロジックを実装するときに、操作しているオブジェクトがよくわからない場合は、まず空であると判断してから操作する必要があります。
  4. 文字列型の null ポインタの場合、比較にオブジェクトを使用できます。
  5. 必須フィールドの入力パラメータの検証
  6. この場合、問題はすでに発生しているため、ログと Arthas ツールを通じて問題を迅速に特定し、迅速に修復してオンラインにし、障害が発生するまでの時間を短縮する必要があります。
  7. その後、コードレビューを強化して自分たちのコードをレビューし、このような状況が再び起こらないようにすることができます。

Null ポインタを通常どのように扱うかを共有できます~

おすすめ

転載: blog.csdn.net/Park33/article/details/130926288