Javaのequalsメソッドから学んだこと
イートスマートの新人エンジニアが、業務の中でコードレビューを受けて学んだことについて書いてみたいと思います。Javaのequalsメソッドを使った例を取り上げます。
Javaのequalsメソッドについて
if (a.equals(b)) {以下省略...のようにaとbが文字列の場合に、文字列aとbが等価であるかどうかを判断し、オブジェクト同士の値が等しければtrueを返します。数値の比較の際には、==を使います。これは、数値がプリミティブ型であるため可能になります。文字列は、オブジェクト型になるため文字列同士をa==bのように比較するとa,bがもっているメモリ上のアドレスを参照して比較を行うことになります。つまり、aとbが同じ値かどうかではなく、同一インスタンスであるかを判断することになります。そのため、文字列の値を比較する際にはequalsで比較するようにします。
実装例
以下に実装例を示します。今回は、実際に業務で使用したコードをアレンジして、元号についての クラスを用意し、01であれば「令和」、02であれば「平成」を返すという仕様で考えてみます。
元号についてのクラス
public class Gengo { private String gengo; public String getGengoKbn() { return gengo; } public void setGengoKbn(String gengo) { this.gengo = gengo; } public String getGengoKbn() { if (定数クラス.GENGO_KBN_REIWA.equals(gengo)) { return "令和"; if (定数クラス.GENGO_KBN_HEISEI.equals(gengo)) { return "平成"; } throw new IllegalStateException(); } }
定数についてのクラス
/** 令和を01とする */ public static final String GENGO_KBN_REIWA = "01"; /** 平成を02とする */ public static final String GENGO_KBN_HEISEI = "02";
実装のポイント
元号の判定をする条件分岐の部分が今回のポイントになります。 実装の際に、以下のようなコードを最初書いておりました。
if (gengo).equals("01")) { return "令和"; } return "平成";
実装例のコードと比較して、良くないポイントがいくつかあるので 以下に整理したいと思います。
①まず、変数gengoは"01"と"02"の他にnullや"03"などが意図せず入る場合も あり、NullPointerExceptionが発生する恐れがあります。 そのため、実装例のように定数.equalsの形にすると、例外の発生を防ぐことができます。
②また、"01"が具体的に何を指すのかが見たときにわかりづらいので、実装例のように
定数として別途定義しておく方が可読性が上がり、検索をかけるときにも"01"が何を
指すのかが明確になります。
さらに、定数クラスでpublic static finalを用いる理由として、staticにするとインスタンスを 作らずにフィールドの利用が可能で、finalにすることで値の変更を不可にできます。以上のこと から、定数としての宣言に用いられ、ここでは外部から利用したいためpublicとしています。
③また、例外をスローする処理もあった方が望ましいので、メソッドの呼び出しに対して オブジェクトの状態が不正の場合を考慮し、IllegalStateExceptionをスローしています。
以上になります。基本的なコードではありますが、後々のメンテナンスのしやすさ、バグを 未然に防ぐといったことをもっと意識する必要があると感じました。