- PR -

文字列をequalsで判定する時

投稿者投稿内容
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2008-02-12 19:32
引用:

Edossonさんの書き込み (2008-02-12 19:28) より:
引用:

# そちら派とこちら派じゃ区別が付かなくなるので、今後、
# 未記入さんにならって、
# そちら派=A派、こちら派=B派としましょうか


まだ続くんですか?



派閥を増やしとかないといけないですからね(笑)
OTAKE
会議室デビュー日: 2008/02/08
投稿数: 18
投稿日時: 2008-02-12 22:35
各派の意見をまとめてみます。
A派(str.equals("hoge")派)…
・主体が左に来ているため読みやすい
・strがnullを許容していないことが一目で分かる
・予期せずstrがnullになると例外が発生するのでバグを見つけやすい
B派("hoge".equals(str)派)…
・strがnullかどうか気にしなくていいのでコードが書きやすい
・strがnullでも例外は発生しないので処理が中断しない
・初心者が多い場合は安全側に倒したい(バグの検出を少なくしたい)
こんなところでいいかな。
キーとなるのは、A派:読みやすい、B派:書きやすい、ですかね。

ところで、strが"//"で始まっているかを調べる場合は、str.startsWith("//")。
strが"sports"より辞書式順で前にあることを調べる場合はstr.compareTo("sports")と、どちらもstrのメソッドを実行します。
一方、strが"book"と等しいかを調べる場合に"book".equals(str)とした場合、前2つの例と比較して気持ち悪さは感じないのでしょうか。

strと別の変数(keyword)を比較する場合、str.equals(keyword)とkeyword.equals(str)のどちらを使うのでしょうか。
比較対象がリテラルから変数に変わっただけで、strを右に持っていくか左に持っていくかが変わるのは、気持ち悪くないでしょうか。
keyword.equals(str)とした場合でも、nullを考慮しないでプログラムを書けるというメリットを失いますが、それでもstrは右でしょうか。

気持ち悪さを感じないのであれば、お互いの意見が交わることはきっと無いでしょう。

nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2008-02-13 01:05
引用:

未記入さんの書き込み (2008-02-12 22:35) より:
・strがnullを許容していないことが一目で分かる



プログラム的には当然許容していませんし、それは理解していれば一目でわかりますが、
作り手が考慮の上で書いているのか不明なので、メリットとはできないでしょうね。

「プログラム的に許容しないことは一目でわかるが、それが作り手の意図なのかはわからない」
さいくろう
大ベテラン
会議室デビュー日: 2005/11/19
投稿数: 170
お住まい・勤務地: 川崎市
投稿日時: 2008-02-13 01:31
気持ち悪い気持ち悪い、そればっかりいってるけどよ、
なんか、小学生の鶴亀算の名人が、中学にあがってから習う
連立二元一次方程式の解法を使うのをいやがる、ってな話を思い出したわ。

<追記>
「二元」が抜けていたので補完

[ メッセージ編集済み 編集者: さいくろう 編集日時 2008-02-13 03:03 ]
OTAKE
会議室デビュー日: 2008/02/08
投稿数: 18
投稿日時: 2008-02-13 02:00
引用:
「プログラム的に許容しないことは一目でわかるが、それが作り手の意図なのかはわからない」


メリットが一つ減ったとしても、コードの読みやすさとバグ検出のしやすさだけでも、十分メリットはあるのですが、少し反論を。
これを言っちゃうと、全てのコードが信用できないってことになりますよ。
例えば、for (int i = 0; i < 9; i++) で、「ループを9回まわしていることは分かるが、それが作り手の意図なのかはわからない(本当はi <= 9で10回まわしたいのかもしれない)」と言うことも主張できるわけで。

そもそも一般的には、リテラルやマジックナンバーを直接使うコード自体が好ましくないので、"hoge".equals(str)なんて使う機会の方が少ないのでしょうね。
さいくろう
大ベテラン
会議室デビュー日: 2005/11/19
投稿数: 170
お住まい・勤務地: 川崎市
投稿日時: 2008-02-13 02:58
引用:

未記入さんの書き込み (2008-02-13 02:00) より:

これを言っちゃうと、全てのコードが信用できないってことになりますよ。
例えば、for (int i = 0; i < 9; i++) で、「ループを9回まわしていることは分かるが、それが作り手の意図なのかはわからない(本当はi <= 9で10回まわしたいのかもしれない)」と言うことも主張できるわけで。


なんか趣旨変わってない?
そもそも「作り手の意図」なんか必要なのか?
書いてあることをそのまま信用すればいい、んでしょうが。

コードに書かれていることは信用するし、信用できるのはそれだけ、
コードに書いてあることがすべて。それ以上でもそれ以下でもない。
では何故いかんの?
つか「書いてもいないものを読み取る」なんて、
保証もない期待に踊らされるようなもの、
百害あって一利無し、だと思うんだけど。
引用:

そもそも一般的には、リテラルやマジックナンバーを直接使うコード自体が好ましくないので、"hoge".equals(str)なんて使う機会の方が少ないのでしょうね。


どうしても必要な定数が発生したら、それは遠慮無く使うよ。
あるいはSingletonなクラスのゲッターメソッドでとってくるとか、
それがプロパティファイルに書かれているとか。

[ メッセージ編集済み 編集者: さいくろう 編集日時 2008-02-13 03:19 ]
まりも
ベテラン
会議室デビュー日: 2006/08/19
投稿数: 77
投稿日時: 2008-02-13 03:18
読んでいろいろ考えてみたのですが、
結論としては、どちらが正しいと明言できる根拠はないように思えました。

つまり、どちらを規約で定めても、その効果は誤差の範囲でプラスマイナス0といえるわけで、
誤差を減らすべく統計的に調査でもしないと結論は出ないのではないかと。



とまあこれだけだとなんなので、
考えてみた途中経過も書いておきます。


まず、未記入さんのまとめを見てもわかりますが、

str.equals("hoge")の利点は、
人間が見て、期待される論理的な意味が判断しやすいこと。

"hoge".equals(str)の利点は、
コンピュータが正しく動くプログラムが書きやすいことと、タイプ量が少ないこと。

ということで。
そういう分け方をすると、どうもstr.equals("hoge")の方が、
特に最近求められている、良いプログラムの条件に当てはまっているようなのですが。


ただ、本当に人間が見やすいのかと言うのがはっきりしてないと思うのです。

日本語でXはYと等しいといった場合、XとYのどちらにリテラルに当たるものが来るか、
日本語としては決まらないでしょう。

決まっているとすれば、それは単に仕様を書く人の慣習なので、
つまり、慣れればどっちでもいいものでしょう。


また、nullのチェックということを考えると。

人間の読む意味的に考えるなら、
nullが入る可能性があるのは単にプログラム上の都合であり、
扱っている論理を考えるならnullなんてことはありえない、
と言う場合も多いのではないでしょうか。

そういう場合であるなら、
nullが考慮されているかされていないかなんてことそのものが、
ポインタ処理なんかと同じようにプログラム上で目立つべきではない低レベルの処理であり、
その辺をあいまいにしている"hoge".equals(str)の方が、
人間に素直に意味を表現できる、と言うこともできます。

などなど考えていくと。
どちらが正しいと明言する根拠は、
私にはわからないというほかはないように思えてきました。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-02-13 05:41
私は自分で書くならB派ですが、
正しく実装してくれるプログラマが書くなら、まぁどっちでもいいです。

引用:

未記入さんの書き込み (2008-02-12 22:35) より:
ところで、strが"//"で始まっているかを調べる場合は、str.startsWith("//")。
strが"sports"より辞書式順で前にあることを調べる場合はstr.compareTo("sports")と、どちらもstrのメソッドを実行します。
一方、strが"book"と等しいかを調べる場合に"book".equals(str)とした場合、前2つの例と比較して気持ち悪さは感じないのでしょうか。



今回の話題の件は、たぶんequalsメソッドの場合だけだと思います。理由は2つ。
他のメソッドと比較してequalsメソッドの現れる頻度が多いというのが1つ目。
それからequalsメソッドがメソッドと言いながら演算子に近い位置づけだからというのが2つ目。
それ以外の例はあまり意味をなさないと思います。(compareToメソッドはひょっとするとB派案を使うかも)

本当は等号演算子で比較したいくらいですが、Javaではequalsメソッドを呼び出す必要がある。
でもって、これはインスタンスメソッドとして用意されている。
というわけで、文法構造上、NullPointerExceptionの存在を考慮する必要がでてくる。
これはJavaの言語としての制約だから、仕方ないわけですが、
純然たる「等しい」の意味を考えると、nullが相手なら等しくなるわけがないので、
そもそもの話としてnullが来る場合は、等しくない、と判定したいパターンしかない。

引用:

strと別の変数(keyword)を比較する場合、str.equals(keyword)とkeyword.equals(str)のどちらを使うのでしょうか。



この場合はB派の手法は使えませんので、A派の人と同じでしょうね。

A派の人が拘るポイントはその人なりの統一感(一貫性)なんでしょう。
私の場合は、基本原則としては一貫性を重視しますが、一貫性をもつことよりも
メリットがあると判断したら、一貫性を捨てます。

ちなみにこれはJavaの言語仕様による制約から来るものですね。
他の言語だとまた話は変わってくるでしょう。
例えば、事前条件を指定できる言語なら、みんなA派に改宗すると思いますよ。


[ メッセージ編集済み 編集者: よねKEN 編集日時 2008-02-13 05:47 ]

スキルアップ/キャリアアップ(JOB@IT)