Java nullポインタ例外ソリューションコレクション(再現)(スレッド "main" java.lang.NullPointerExceptionの例外)

1)不明なオブジェクトではなく、既知のStringオブジェクトからequals()メソッドとequalsIgnoreCase()メソッドを呼び出します。

既知の空でないStringオブジェクトから常にequals()メソッドを呼び出します。equals()メソッドは対称であるため、a.equals(b)の呼び出しとb.equals(a)の呼び出しはまったく同じです。そのため、プログラマーはオブジェクトaとbについて非常に不注意です。呼び出し元がnullポインターの場合、この呼び出しによりnullポインター例外が発生する可能性があります

 Object unknownObject = null;
//错误方式 – 可能导致 NullPointerException
if (unknownObject.equals("knownObject")) {
        System.err.println("This may result in NullPointerException if unknownObject is 
        null");
}
//正确方式 - 即便 unknownObject是null也能避免NullPointerException
if ("knownObject".equals(unknownObject)) {
        System.err.println("better coding avoided NullPointerException");
}


これは、nullポインタの例外を回避するための最も単純なJava手法ですが、equals()が一般的なメソッドであるため、大幅な改善につながる可能性があります。

2)valueOf()とtoString()が同じ結果を返す場合は、前者を使用します。

nullオブジェクトのtoString()を呼び出すと、nullポインター例外がスローされるため、valueOf()を使用して同じ値を取得できる場合は、valueOf()を使用し、valueOf()にnullを渡すと、特に「null」が返されます。 Integer、Float、Double、BigDecimalなどのパッケージングクラス。

BigDecimal bd = getPrice();
System.out.println(String.valueOf(bd)); //不会抛出空指针异常
System.out.println(bd.toString()); //抛出 "Exception in thread "main" java.lang.NullPointerException"


3)nullセーフなメソッドとライブラリを使用します。大量のnullポインタチェックを実行したオープンソースライブラリが多数あります。最も一般的に使用されるものの1つは、ApacheコモンズのStringUtilsです。StringUtils.isBlank()、isNumeric()、isWhiteSpace()、およびその他のツールメソッドを、nullポインターの例外を気にせずに使用できます。

//StringUtils方法是空指针安全的,他们不会抛出空指针异常
System.out.println(StringUtils.isEmpty(null));
System.out.println(StringUtils.isBlank(null));
System.out.println(StringUtils.isNumeric(null));
System.out.println(StringUtils.isAllUpperCase(null));
 
Output:
true
true
false
false


 
ただし、結論を出す前に、nullポインタメソッドのクラスのドキュメントを読むことを忘れないでください。これは、多くの労力をかけずに大幅に改善できるもう1つのJavaのベストプラクティスです。

4)メソッドからnullポインターを返すことは避けますが、空のコレクションまたは空の配列を返します。

このJavaのベストプラクティスまたはテクニックは、JoshuaBlochの著書EffectiveJavaで言及されています。これは、Javaプログラミングをより適切に使用できるもう1つの手法です。空のコレクションまたは空の配列を返すことにより、nullポインターの例外が原因でsize()、length()などの呼び出しがクラッシュしないようにすることができます。Collectionsクラスは、便利な空のリスト、セット、およびマップを提供します:Collections.EMPTY_LIST、Collections.EMPTY_SET、Collections.EMPTY_MAP。これが例です。

public List getOrders(Customer customer){
List result = Collections.EMPTY_LIST;
return result;
}


nullポインタの代わりにCollections.EMPTY_SETとCollections.EMPTY_MAPを使用することもできます。

5)annotation @NotNullおよび@Nullableを使用します

プログラムを作成するときに、それがnullポインタになるかどうかを定義できます。@NotNullや@Nullableなどの注釈を使用して、メソッドがnullポインタセーフであるかどうかを宣言します。最新のコンパイラ、IDE、またはツールは、この注釈を読み取って、忘れたnullポインタチェックを追加したり、不要な厄介なnullポインタチェックを要求したりするのに役立ちます。IntelliJとfindbugsは、すでにこれらの注釈をサポートしています。これらの注釈もJSR305の一部ですが、IDEまたはツールにない場合でも、注釈自体をドキュメントとして使用できます。@NotNullと@Nullableを見て、プログラマーはnullポインターをチェックするかどうかを決定できます。ちなみに、この手法はJavaプログラマーにとっては比較的新しい手法であり、採用するには時間がかかります。

6)コード内の不要な自動パッケージ化と自動アンパックを回避します。

一時オブジェクトの作成などの他の欠点に関係なく、ラッパークラスオブジェクトがnullの場合、自動折り返しによってnullポインタ例外が発生する傾向もあります。たとえば、personオブジェクトに電話番号がない場合、nullが返されます。nullポインタの例外が原因で、次のコードがクラッシュします。

Person ram = new Person("ram");
int phone = ram.getPhone();


自動パッケージングと自動アンパックングを使用すると、等号だけでなく、nullポインター例外もスローされます。この記事では、Javaでの自動パッケージ化とアンパックの落とし穴について詳しく知ることができます。

7)契約に従い、妥当なデフォルト値を定義します。

Javaでnullポインタの例外を回避する最良の方法の1つは、単にコントラクトを定義してそれに従うことです。ほとんどのヌルポインタ例外は、オブジェクトが不完全な情報で作成されているか、すべての依存関係が提供されていないために発生します。不完全なオブジェクトの作成を許可せず、これらの要求を適切に拒否する場合、後続のワーカーで多数のnullポインター例外を防ぐことができます。同様に、オブジェクトの作成が許可されている場合は、それらの適切なデフォルト値を定義する必要があります。たとえば、従業員オブジェクトはIDと名前なしでは作成できませんが、電話番号があるかどうかはオプションです。これで、従業員が電話番号を持っていない場合、nullを返す代わりに、デフォルト値(0など)を返すことができます。ただし、慎重に選択する必要があります。無効な番号を呼び出すよりも、nullポインタをチェックする方が便利な場合があります。同様に、何をnullにできるか、何をnullにできないかを定義することにより、呼び出し元は情報に基づいた決定を行うことができます。速く失敗するか、nullを受け入れることも、選択して実装する必要がある重要な設計上の決定です。

8)データベースのフィールドを空にすることができるかどうかを定義します。

データベースを使用してCustomers、Ordersなどのドメイン名オブジェクトを格納している場合は、データベース自体にnull制約を定義する必要があります。データベースは多くのコードからデータを取得するため、データが正常であることを確認するために、データベースが空であるかどうかを確認するチェックがあります。データスペースでnull制約を維持すると、Javaコードでのnullポインタチェックを減らすのにも役立ちます。データベースからオブジェクトをロードするときに、どのフィールドをnullにすることができ、どのフィールドをnullにすることができないかが明確になります。これにより、コード内の不要な!= nullチェックを最小限に抑えることができます。

9)ヌルオブジェクトパターンを使用する

Javaでnullポインタ例外を回避する別の方法があります。メソッドがオブジェクトを返す場合、呼び出し元でいくつかの操作を実行します。たとえば、Collection.iterator()メソッドは反復子を返し、呼び出し元はトラバーサルを実行します。呼び出し元にイテレーターがない場合、nullではなくNullオブジェクトを返すことができると想定します。空のオブジェクトは特別なオブジェクトであり、コンテキストごとに意味が異なります。たとえば、hasNext()を呼び出すとfalseが返される場合、空のイテレータを空のオブジェクトにすることができます。同様に、コンテナタイプとコレクションタイプを返すメソッドの例では、戻り値としてnullの代わりに空のオブジェクトを使用できます。空のオブジェクトパターンに関する別の記事を書き、Javaの空のオブジェクトの例をいくつか共有する予定です。

おすすめ

転載: blog.csdn.net/qq_36766417/article/details/105988180