2つのStrings
を比較するとき、==
にはいくつかの問題があることを私は知っています。 String.equals()
がより良いアプローチであるようです。さて、私はJUnitテストをしています、そして私の志向はassertEquals(str1, str2)
を使うことです。これは、2つの文字列に同じ内容が含まれていると主張するための信頼できる方法ですか?私はassertTrue(str1.equals(str2))
を使用しますが、その場合、期待値と実際の値が失敗したことを確認してもメリットはありません。
関連するメモで、誰かがstr1 == str2
に関する問題を明白に説明しているページまたはスレッドへのリンクを持っていますか?
JavaでStrings
を比較するときは、常に常に.equals()
を使用する必要があります。
JUnitは.equals()
メソッドを呼び出して、メソッドassertEquals(Object o1, Object o2)
の等価性を判断します。
だから、あなたはassertEquals(string1, string2)
を使って間違いなく安全です。 (String
sはObject
sなので)
assertEquals
は、比較にequals
メソッドを使用します。 ==
演算子を使用する別のアサートassertSame
があります。
==
が文字列と一緒に使用されるべきでない理由を理解するためには、==
が何をするのか理解する必要があります:それはアイデンティティチェックをします。つまり、a == b
は、a
とb
が同じオブジェクトを参照しているかどうかを確認します。これは言語に組み込まれており、その動作は異なるクラスによって変更することはできません。一方、equals
メソッドはクラスでオーバーライドできます。 (Object
クラスの)デフォルトの動作は==
演算子を使用してアイデンティティチェックを行うことですが、String
を含む多くのクラスはそれをオーバーライドして代わりに「等価」チェックを行います。 String
の場合、a
とb
が同じオブジェクトを参照しているかどうかを確認する代わりに、a.equals(b)
は参照しているオブジェクトが両方ともまったく同じ文字を含む文字列であるかどうかを確認します。
同じような時:それぞれのString
オブジェクトは何かが書かれた一枚の紙であると想像してください。 "Foo"が書かれた2枚の紙と、 "Bar"が書かれた別の紙があるとしましょう。最初の2枚の紙を取り、それらを比較するために==
を使用すると、それは本質的に「これらは同じ紙ですか?」と尋ねるのでfalse
を返します。紙に書かれていることを見る必要さえありません。 2枚の紙を(同じ紙を2回ではなく)2枚渡しているということは、false
が返されることを意味します。しかし、equals
を使用すると、equals
メソッドは2枚の紙を読み、それらが同じこと( "Foo")を言っていることがわかるので、true
を返します。
文字列と混乱してしまうのは、Javaには「内部」文字列という概念があり、これが(事実上)コード内の任意の文字列リテラルに対して自動的に実行されることです。つまり、コード内に2つの同等の文字列リテラルがある場合(それらが異なるクラスに属していても)、実際には両方とも同じString
オブジェクトを参照します。これにより、==
演算子はtrue
を予想以上に頻繁に返します。
一言で言えば - 同じ文字を含むが異なるオブジェクト(異なるメモリ位置にある)である2つのStringオブジェクトを持つことができます。 ==演算子は2つの参照が同じオブジェクト(メモリ位置)を指していることを確認しますが、equals()メソッドは文字が同じかどうかを確認します。
通常、2つの文字列が同じ文字を含んでいるかどうかを確認することに興味があります。それらが同じメモリ位置を指しているかどうかではありません。
はい、それはテストのためにいつも使われています。このような比較のためにテストフレームワークが.equals()を使用する可能性が非常に高いです。
以下は「文字列の等価性の誤り」を説明するリンクです。基本的に、Javaの文字列はオブジェクトであり、オブジェクトの等価性を比較すると、通常、コンテンツではなくメモリアドレスに基づいて比較されます。このため、内容が同一であっても、2つの文字列が同じアドレスを占有することはありません。したがって、印刷時に同じに見えても、正しく一致しません。
http://blog.enrii.com/2006/03/15/Java-string-equality-common-mistake/
public class StringEqualityTest extends TestCase {
public void testEquality() throws Exception {
String a = "abcde";
String b = new String(a);
assertTrue(a.equals(b));
assertFalse(a == b);
assertEquals(a, b);
}
}
JUnitのassertEquals(obj1, obj2)
は実際にobj1.equals(obj2)
を呼び出します。
obj1 == obj2
を実行するassertSame(obj1, obj2)
もあります(つまり、obj1
とobj2
が同じインスタンスを参照していることを確認します)、これは避けようとしていることです。
だから大丈夫です。
"
==
演算子は、2つのObjects
がまったく同じObject
であるかどうかを確認します。"
http://leepoint.net/notes-Java/data/strings/12stringcomparison.html
String
はJavaのObject
なので、そのカテゴリの比較規則に分類されます。