今日も元気に真人間

好き: 中日 、アニソン 、中本 、IT 、乃木坂46(乃木坂って、どこ?、乃木坂工事中)

定数と変数の比較に関する文句

Javaを習って間もない頃、文字列型の比較は==を使ってはダメで、equals()メソッドを使わないといけないということを習う。
等価と等値の違いで、==での比較は同一インスタンスかどうかの等値判定、equals()メソッドでの比較はインスタンスの中身が同じかの等価判定を行う。String型は参照型なので、等価と等値は明確に区別されなければならない。

もう少し実践的にJavaを使うようになると、このequals()メソッドでString型の変数と定数を比較する際に「定数.equals(変数)」という形で書きなさいという教えを受ける。逆に書くと変数にnullが来たときにNullPointerExceptionが発生するが、この形で書けば発生しないからである。つまり、変数のnullチェックを省略できる。

が、私はこれが気に入らない。「定数.equals(変数)」と「変数.equals(定数)」では明確に前者にメリットがあり後者には特にメリットがないことは間違いないのだが、それでも気に入らない。


■数式的に違和感がある
これが一番直感的な理由。数学の文脈で文章を書いているときに「x=0のとき」と書くべきところで急に「0=xのとき」とか書き始めたら普通違和感を抱くだろう。ソースコード命名含めて英語を読むように直感的に読めるのがきれいな形だと思っているので、直感に反するというのは私にとって大きな悪である。


■入れ替えると結果が変わるというのが気に入らない
同一かどうかの比較というのは普通に考えて、対象の2つを入れ替えてもその結果は変わらないべきである。しかし実際には、場合によってfalseが返ってきたりNullPointerExceptionが発生したりと、結果が変わってしまう。なのでそもそもString型のequals()メソッドの作りがイケていないと思っている。
ちなみに関係Rが対称律を満たすとは、「xRy ⇒ yRx」を満たすことなので、別に満たすべき性質を満たしていないと言うほどのことではない。trueが返ってくるようなケースであれば、2つ入れ替えても同じようにtrueが返ってくるからである。
java.sql.Timestampクラスのequals()メソッドなんかは、この対称律さえ満たしていない。

ponkotuy.hatenadiary.org

今ではObjects.equals()メソッドが、引数を2つ取って順番関係なしに比較をしてくれるので、こちらの方が私の直感には合っている。


■本来するべきnullチェックをサボっているだけである
そもそもnullが来るかもしれない場合に備えて保険をかけているのがおかしい。nullが来るかもしれない変数を扱う場合にはnullチェックを適切に行うべきであり、それが漏れているにすぎない。チェックすべき箇所がこの1か所だけなのであれば省略できて嬉しいというのは分かるが、往々にしてそんなことはないので、equals()部分を乗り切っても問題を先送りにしているだけである。

 

と、文句を言ってはみたものの、「定数.equals(変数)」と書くことに特にデメリットはないことは確かなので、文句を言いながらもこう書き続けることだろう。