enum の比較は安心して == を使ってください

f:id:Naotsugu:20130920233746p:plain



はじめに

どこのプロジェクトでも多くの人が enum を equals で比較していることが多いです。
でも enum のインスタンスは単一であることが保証されているので、安心して == で比較することができます(Elvisは1人しか存在しないのです)。



enum の == 比較はコンパイル時に型チェックが行われる

以下の2つのenumがあった場合、

public enum Color {
    RED, GREEN, BLUE;
}

public enum Season {
    WINTER, SPRING, SUMMER, FALL;
}

 

equals による比較は異なる型を比較してしまっているにも関わらずコンパイルエラーにはなりません。

Color.RED.equals(Season.SPRING)

これだと一目瞭然ですが、以下のような場合は非常にわかりずらいです。

getCurrent().equals(Season.SPRING)

 

もちろん == による比較はコンパイルエラーになります。

Color.RED == Season.SPRING // error!!

 

この点が == で比較すべき一番のポイントになります。
とは言え、Findbugs で警告になるので発見は可能です。


enum の == 比較は null セーフである

以下の比較は想像通りの動きをします。

Season now = null;
if (now == Season.SUMMER) {

 

以下のコードはヌルポです。

Season now = null;
if (now.equals(Season.SUMMER)) {


この例は見方によって、どちらがよいかは微妙なところがあります。
now には必ず値が設定されているはずであれば(単なるバグなので)ヌルポで落としてあげるのが良いコードです。
論理的に見ると、now は未設定で Season.SUMMER ではないので、その通りに判定してあげるのが良いです。


そういった意味で最悪なのは、

Season now = null;
if (Season.SUMMER.equals(now)) {

ヌルポにもならずに単にfalseとなります。


ということで、(nullを許可したくない場合の)最良なコードは

public void foo(Season currentSeason) {
    Objects.requireNonNull(currentSeason);

    if (currentSeason == Season.SUMMER) {
        ・・・
    }

のように事前条件を明示的に記載するものになるでしょう。


enum の == 比較は読みやすい

どちらが読み易いでしょうか。

if (now == Season.SUMMER);
if (now.equals(Season.SUMMER));

人によるかも知れませんが、私は上を選びます。


enum の == 比較はちょっとだけ早いかもしれない

コンパイラの最適化などで変わると思いますが、すくなくとも == での比較の方が遅くなることがないでしょう。


ということで、enum は == で比較していきましょう。