NullPointerException を好む人はいません。それらを回避する方法はありますか?多分。 。
この記事では次のテクノロジーについて説明します
1.オプション型(Java 8で新たに導入)
2.Objects クラス (Java 7 のオリジナル)
Java 8のオプションのクラス
それは何ですか?
1. Java 8 で導入された新しい型
2. 指定されたタイプのオブジェクトのラッパーとして、またはオブジェクトが存在しない (null) シナリオで使用されます。
簡単に言えば、これは null 値を処理するためのより良い代替手段です (警告: 一見しただけでは明らかではないかもしれません)
基本的な使い方
これは型 (クラス) です。では、この型のインスタンスを作成するにはどうすればよいでしょうか?
3 つの静的メソッドを使用するだけです。
次のようにコードをコピーします。
public static Optional<String> stringOptional(String input) {
戻り値 Optional.of(input);
}
シンプルかつ明確 - この値を含むオプションのラッパーを作成します。この値が null の場合、NPE がスローされることに注意してください。
次のようにコードをコピーします。
public static Optional<String> stringNullableOptional(String input) {
if (!new Random().nextBoolean()) {
入力 = null;
}
Optional.ofNullable(入力)を返します。
}
個人的にはその方が良いと思います。この方法では、NPE のリスクはなくなります。入力が null の場合は、空の Optional が返されます。
次のようにコードをコピーします。
public static Optional<String> emptyOptional() {
戻り値 Optional.empty();
}
本当に「null」値を返したいだけの場合。 「空」の値は null を意味しません。
さて、オプションを消費/使用するにはどうすればよいですか?
次のようにコードをコピーします。
public static void usingOptional() {
Optional<String> ラップ = Optional.of("aString");
if (wrapped.isPresent()) {
System.out.println("文字列を取得しました - " + Wrapped.get());
}
それ以外 {
System.out.println("気づいた!");
}
}
簡単な方法は、Optional ラッパーに実際に値があるかどうかを確認することです (isPresent メソッドを使用します)。これが if(myObj != null) を使用する場合と比較してどのような利点があるのか疑問に思うでしょう。心配しないでください、明確に説明します。
次のようにコードをコピーします。
public static void usingNullableOptional() {
文字列入力 = null;
if (new Random().nextBoolean()) {
入力 = "iCanBeNull";
}
Optional<String> ラップ = Optional.ofNullable(input);
System.out.println(wrapped.orElse("default"));
}
orElse メソッドを使用すると、カプセル化された値が実際に null 値である場合に、それを使用してデフォルト値を返すことができます。その利点は明らかです。実際の値を抽出する場合、ifPresent メソッドを呼び出すという明らかに冗長な方法を回避できます。
次のようにコードをコピーします。
public static void usingEmptyOptional() {
文字列入力 = null;
if (new Random().nextBoolean()) {
入力 = "iCanBeNull";
}
Optional<String> ラップ = Optional.ofNullable(input);
System.out.println(wrapped.orElseGet(
() -> {
「デフォルトのサプライヤー」を返します;
}
));
}
これについては少し混乱しています。同じ目的に対して 2 つの異なる方法があるのはなぜですか? orElse と orElseGet は明らかにオーバーロードできます (名前は同じですがパラメーターが異なります)。
とにかく、これら 2 つのメソッドの明らかな違いはパラメータです。これを実現するには、Supplier のインスタンスの代わりにラムダ式を使用することを選択できます (関数型インターフェイス)。
Optional を使用する方が一般的な null チェックよりも優れているのはなぜですか?
1. Optional を使用する最大の利点は、意図をより明確に表現できることです。null 値を返すと、(NPE が発生した場合に) これが意図的に返されたかどうか消費者が混乱するため、詳細については javadoc を確認する必要があります。 。 Optional の使用は非常に簡単です。
2. Optional を使用すると、NPE を完全に回避できます。前述したように、Optional.ofNullable、orElse および orElseGet を使用すると、NPE を回避できます。
もう一人の救世主!
このコード スニペットを見て、以下のコードをコピーしてください。
パッケージ com.abhirockzz.wordpress.npesaviors;
java.util.Mapをインポートします。
java.util.Objectsをインポートします。
パブリック クラス usingObjects {
String getVal(Map<String, String> aMap, String key) {
aMap.containsKey(key) を返しますか? aMap.get(key) : null;
}
public static void main(String[] args) {
usingObjects obj = new usingObjects();
obj.getVal(null, "ダミー");
}
}
どれが空いているでしょうか?
1.マップオブジェクト
2. 検索に使用するキー
3. このメソッド呼び出しのインスタンス
NPE がスローされた場合、どれが null であるかをどのように判断すればよいでしょうか?
次のようにコードをコピーします。
パッケージ com.abhirockzz.wordpress.npesaviors;
java.util.Mapをインポートします。
java.util.Objectsをインポートします。
パブリック クラス usingObjects {
String getValSafe(Map<String, String> aMap, String key) {
Map<String, String>safeMap = Objects.requireNonNull(aMap,
"マップは null");
StringsafeKey = Objects.requireNonNull(key, "キーが null");
戻りsafeMap.containsKey(safeKey) : null;
}
public static void main(String[] args) {
usingObjects obj = new usingObjects();
obj.getValSafe(null, "ダミー");
}
}
requireNonNull メソッド
1. オブジェクトが null でない場合は、それ自体を返します
2. 値が null の場合、返される NPE には指定されたメッセージが含まれます。
if(myObj!=null) よりも優れているのはなぜですか?
スタック トレースを見ると、Objects.requireNonNull メソッド呼び出しがはっきりとわかります。これを独自のエラー ログと組み合わせることで、問題をより迅速に特定できるようになります。 。 。少なくとも私の意見ではその方が速いと思います。
Null 値がないことを確認するための単純なバリデータを実装するなど、独自のバリデータをカスタマイズすることもできます。
次のようにコードをコピーします。
java.util.Collectionsをインポートします。
java.util.Listをインポートします。
java.util.Objectsをインポートします。
インポート java.util.function.Predicate;
パブリック クラス RandomGist {
public static <T> T requireNonEmpty(T object, Predicate<T> predicate, String msgToCaller){
Objects.requireNonNull(オブジェクト);
Objects.requireNonNull(述語);
if (predicate.test(object)){
新しい IllegalArgumentException(msgToCaller) をスローします。
}
オブジェクトを返します。
}
public static void main(String[] args) {
//使用法 1: 空の文字列 (意図的)
文字列 s = "";
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "私の文字列は空です!"));
//使用法 2: 空のリスト (意図的)
リスト list = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "リストは空です!").size());
//使用法 3: 空のユーザー (意図的)
ユーザー user = new User("");
System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "ユーザーは空です!"));
}
プライベート静的クラス ユーザー {
プライベート文字列名。
public User(文字列名){
this.name = 名前;
}
public String getName(){
名前を返します。
}
}
}
NPE を間違ったところで面倒なものにしないでください。私たちは、NPE に適切に対処し、完全に根絶するためのツールを多数持っています。