0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

等価判定のNullPonterExceptionの回避方法〜

Last updated at Posted at 2022-07-02

目的

  • Javaの等価判定でNullPonterExceptionが発生してしまう場合の、回避方法を学ぼう

対象読者

  • Java入門者
  • Javaの等価判定をなんとなくでコードを記載している
  • 等価判定ってなに?って人

等価判定とは

複数のオブジェクトが同じであればtrue,異なればfalseとなることを言います。
似たような比較に等値判定がありますが、使用方法は若干違います。

等価判定の使用方法

オブジェクトを生成して、実際に等価判定を行ってみました。

Main.java
// 等価判定の場合
// 型:String
String s1 = "サンプル";
String s2 = "サンプル";
String s3 = "さんぷる";

System.out.println("s1,s2を比較" + s1.equals(s2));
System.out.println("s1,s3を比較" + s1.equals(s3));

実行結果
true
false
解説

equalsで比較をしていることに注目してみよう。
まず、結果はtruefalseが表示されている。
オブジェクトの比較としては、最初はs1s2で中身が両方サンプル、次の比較がs1s3で中身が両方同一ではないことが確認できます。
それによって、オブジェクトの中身が同一であれば、true、同一でなければfalseというのが想像できると思います。

等値判定の使用方法

オブジェクトを生成して、実際に等値判定を行ってみました。

Main.java
// 等値判定の場合
// 型:String
String s1 = "サンプル";
String s2 = "サンプル";
String s3 = s1;

System.out.println("s1,s2を比較" + s1 == s2);
System.out.println("s1,s3を比較" + s1 == s3);

実行結果
false
true
解説

先ほど(equals)とは違う == で比較をしていることに注目してみよう。
まず、結果はfalsetrueが表示されている。
オブジェクトの比較としては、最初はs1s2で中身が両方サンプル、次の比較がs1s3で中身が同一であることが確認できます。
ただ先ほどとは違い、オブジェクトの中身を比較しているようには見えません。
中身を比較していたら、先ほどの下記のような結果になるのは想定できるはずです。

それによって、オブジェクトの中身が同一であれば、true、同一でなければfalseというのが想像できると思います。

まず比較対象としては、オブジェクトの参照値となります。
オブジェクトの参照値となりますが、詳しくは話さないため、下記などを参考にしてください。

参照値について、理解したら結果がs1s3trueなのは理解できたはずです。

(補足)s1の参照値がs3に入ってるのは、上記コードから読み取れたはずです。

さて、いよいよ等価判定のNullPointerExceptionの回避方法を説明しよう

等価判定〜NullPointerExceptionの回避方法

今回の方法としては、DTOに詰められているデータに対しての等価判定を行う場合となります。
(データベース設計に関しては、無視してください...)

DTO.java
// 名前
private String name;

public String getname(){
    return name;
}

public void setname(String name){
    this.name = name;
}

Logic.java
// インスタンス生成
private DTO dto;

// 等価判定
// 例えがおかしいですが...(nameに固定値が...
if(dto.getname().equals("山田"){ // ここで異常終了

}else{
    if(StringUtils.isEmpty(dto.getname())){
    }
}

この製造の仕方だと、テストケースで引っかかるとは思いますが、NullPointerの例外が発生します。
なぜかという比較しようとしているdto.getname() がnullが来た場合、比較できないので例外が発生しますよね...

自分はもちろん経験済みですが

回避策としては、下記があるのかなと思っています。(それ以外思い浮かばず...)

  1. 固定値がくることがあれば定数を左に持ってくる
  2. Nullチェックを先に判定する。
  3. 『Objects.equals()』を使用する
  4. 『StringUtils.equals()』を使用する。

定数を左

Logic.java
// インスタンス生成
private DTO dto;

// 等価判定
+ // 1の場合
+ final String KEY_WORD = "山田";
+ if(KEY_WORD.equals(dto.getname());
- // 例えがおかしいですが...(nameに固定値が...
- if(dto.getname().equals("山田"){ 
 // 処理記述
}else{
     if(StringUtils.isEmpty(dto.getname())){
     // 処理記述
    }
}

nullチェックを先に行う

Logic.java
// インスタンス生成
private DTO dto;

// 等価判定
+ // 2の場合
+ if(StringUtils.isEmpty(dto.getname())){
 // 本来は処理記述
}else{
- // 例えがおかしいですが...(nameに固定値が...
    if(dto.getname().equals("山田"){
     // 処理記述
    }
}

Objects.equalsの使用

Logic.java
// インスタンス生成
private DTO dto;

// 等価判定
+ // 3の場合
- // 例えがおかしいですが...(nameに固定値が...
-   if(dto.getname().equals("山田"){
+   if(Objects.equals(dto.getname(),"山田"){   
     // 処理記述
    }
}

StringUtils.equalsの使用

Logic.java
// インスタンス生成
private DTO dto;

// 等価判定
+ // 4の場合
- // 例えがおかしいですが...(nameに固定値が...
-   if(dto.getname().equals("山田"){
+   if(StringUtils.equals(dto.getname(),"山田"){   
     // 処理記述
    }
}

番号 想定される使用方法
1 予め判定を行う片方が"固定値"であれば、使用できる想定です。
2 空,nullチェックを先に行う理由は、ぬるぽ回避ぐらいですかね...
3 比較する対象がどちらも"null"要素が入る場合、使用するのが望ましいんですかね。
4 比較する対象がどちらも"null"要素が入る場合、使用するのが望ましいんですかね。

3番と4番の違いがそこまで理解できてなく....

一旦はこんな形で回避できるの中〜って思っています。
最後まで見ていただき、ありがとうございます。
※誤りが合った場合、適宜修正は行っていきます。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?