私がこれを正しく理解しているかどうかを明確にしたいと思いました:
==
参照比較です。つまり、両方のオブジェクトが同じメモリ位置を指します.equals()
オブジェクトの値の比較を評価します
.equals()
として有意義同等
私がこれを正しく理解しているかどうかを明確にしたいと思いました:
==
参照比較です。つまり、両方のオブジェクトが同じメモリ位置を指します.equals()
オブジェクトの値の比較を評価します.equals()
として有意義同等
回答:
一般的に、あなたの質問に対する答えは「はい」ですが...
.equals(...)
比較するために書かれたものだけを比較します。それ以上でもそれ以下でもありません。equals(Object o)
このメソッドをオーバーライドした最も近い親クラスのメソッドになります。Object#equals(Object o)
ます。オブジェクトAPIによると、これはと同じ==
です。つまり、両方の変数が同じオブジェクトを参照し、それらの参照が同じである場合にのみ、 trueを返します。したがって、機能の等価性ではなく、オブジェクトの等価性をテストします。hashCode
場合は、必ずオーバーライドすることを忘れないでくださいequals
。APIによると、hashCode()
2つのオブジェクトのメソッドから返された結果は、それらのメソッドが同等であることが示されている場合、同じでなければなりませんequals
。逆は必ずしも真実ではありません。==
メモリ参照をチェックする場合、なぜ[this] [1] [1]でこの奇妙な動作が発生するのですか:docs.google.com/document/d/… 出力がtrueであると期待していました。私の混乱を取り除くことができます
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
<BR/> Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
(docs.oracle.com/javase/7/docs/api/java/lang/...)
Stringクラスに関して:
equals()メソッドは、2つのオブジェクト参照が同じStringインスタンスを参照しているかどうかに関係なく、(ヒープ上の)Stringインスタンス内の「値」を比較します。タイプStringの2つのオブジェクト参照が同じStringインスタンスを参照している場合、すばらしいです!2つのオブジェクト参照が2つの異なるStringインスタンスを参照している場合、違いはありません。比較される各Stringインスタンス内のその「値」(つまり、文字配列の内容)。
一方、「==」演算子は2つのオブジェクト参照の値を比較して、同じStringインスタンスを参照しているかどうかを確認します。両方のオブジェクトの値が同じStringインスタンスを「参照」する場合、ブール式の結果は「true」です。一方、両方のオブジェクトの値が異なるStringインスタンスを「参照」している場合(両方のStringインスタンスが同じ「値」を持っている場合、つまり、各Stringインスタンスの文字配列の内容が同じである場合)、ブール式の結果は「false」になります。
他の説明と同様に、それを沈み込ませてください。
これで状況が少しよくなるといいですね。
String
sが、==
参照がはい、同様に等しいですが、それは通常、(2つのように動作しString
ます同じ内容のS 通常ことが==
あるためどのようにJavaのハンドルの、お互いに)String
S。それは常に起こるとは限らず、それは確かに悪い習慣ですが、特に他の言語から来ている人々からの一般的な間違いです。
String
文字列リテラルからのビルドはと呼ばれるものに追加されますString constant pool
、例えばString s1 = "someString"; String s2 = "someString;"
、両方s1
&s2
同じ参照を共有します。 s1 == s2
trueを返します。しかし、それらがを介して構築された場合String constructor
、たとえばString s1 = new String("someString"); String s2 = new String("someString");
、それらは同じ参照を共有しません。s1 == s2
falseを返します。
「プリミティブ」と「オブジェクトタイプ」のどちらを話しているかに応じて、いくつかの小さな違いがあります。「静的」または「非静的」メンバーについて話している場合も同じことが言えます。上記のすべてを混ぜることもできます...
次に例を示します(実行できます)。
public final class MyEqualityTest
{
public static void main( String args[] )
{
String s1 = new String( "Test" );
String s2 = new String( "Test" );
System.out.println( "\n1 - PRIMITIVES ");
System.out.println( s1 == s2 ); // false
System.out.println( s1.equals( s2 )); // true
A a1 = new A();
A a2 = new A();
System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
System.out.println( a1 == a2 ); // false
System.out.println( a1.s == a2.s ); // true
System.out.println( a1.s.equals( a2.s ) ); // true
B b1 = new B();
B b2 = new B();
System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
System.out.println( b1 == b2 ); // false
System.out.println( b1.getS() == b2.getS() ); // false
System.out.println( b1.getS().equals( b2.getS() ) ); // true
}
}
final class A
{
// static
public static String s;
A()
{
this.s = new String( "aTest" );
}
}
final class B
{
private String s;
B()
{
this.s = new String( "aTest" );
}
public String getS()
{
return s;
}
}
これらのリンクを通じて、「==(等値演算子)」と「.equals(...)」(java.lang.Objectクラスのメソッド)の説明を比較できます。
==とequalsの違いは、詳しく調べるまで、しばらくの間混乱していました。それらの多くは、文字列を比較するために使用すべきであり、使用すべきではequals
ないと述べてい==
ます。この答えで私が違いを言えることを願っています。
この質問に答える最良の方法は、いくつか質問することです。それでは始めましょう:
以下のプログラムの出力は何ですか:
String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);
あなたが言うなら、
false
true
私はあなたが正しいと言いますが、なぜあなたはそれを言ったのですか?そして、あなたが出力がそうであると言うならば、
true
false
私はあなたが間違っていると言いますが、私はまだあなたに尋ねます、なぜあなたはそれが正しいと思いますか?
では、これに答えてみましょう。
以下のプログラムの出力は何ですか:
String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);
今あなたが言うなら、
false
true
私はあなたが間違っていると言いますが、なぜ今間違っているのですか?このプログラムの正しい出力は
true
false
上記のプログラムを比較して、考えてみてください。
OK。これが役立つかもしれません(これを読んでください:オブジェクトのアドレスを出力してください-不可能ですが、それでも使用できます)。
String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));
上記のコードの最後の3行の出力について考えてみてください。私はこれを印刷しました(ここでコードを確認できます)。
false
true
true
false
mango mango
false
true
17225372
17225372
5433634
ああ!これで、identityHashCode(mango)がidentityHashCode(mango2)と等しいことがわかりますが、identityHashCode(mango3)とは異なります。
すべての文字列変数-mango、mango2、mango3-の値は同じですが、「mango」identityHashCode()
はすべての値が同じではありません。
今度はこの行のコメントを外し// mango2 = "mang";
てもう一度実行してみてくださいidentityHashCode()
。今回は3つすべてが異なることがわかります。参考になるヒントですね
if hashcode(x)=N
とhashcode(y)=N
=>x is equal to y
javaが内部でどのように動作するかはわかりませんが、私が言ったときにこれが起こったと思います:
mango = "mango";
javaは、次のような"mango"
変数によってポイント(参照)された文字列を作成しましたmango
mango ----> "mango"
今私が言った次の行で:
mango2 = "mango";
それは実際に"mango"
このようなものに見える同じ文字列を再利用しました
mango ----> "mango" <---- mango2
mangoとmango2の両方が同じ参照を指している
mango3 = new String("mango")
実際には、「mango」の完全に新しい参照(文字列)が作成されました。こんな感じです
mango -----> "mango" <------ mango2
mango3 ------> "mango"
だから、の値をmango == mango2
出すと、が出true
ます。そして、私がの値を出したときmango3 == mango2
、それはfalse
(値が同じであったとしても)出しました。
そして、行をコメント解除する// mango2 = "mang";
と、実際には次のようにグラフを回す文字列「mang」が作成されました。
mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"
これが、identityHashCodeがすべてで同じではない理由です。
これが皆さんのお役に立てば幸いです。実際、==が失敗し、equals()がパスするテストケースを生成したかったのです。遠慮なくコメントして、間違っている場合はお知らせください。
mango == mango2
あなたが作成していないために起こるmango2
新しいStringオブジェクトとして、そしてだけではなく、直接参照しますか"mango"
?
== 2つの変数が持っているかどうかをオペレータテスト(メモリアドレスへのポインタ別名)と同じ参照を。
String foo = new String("abc");
String bar = new String("abc");
if(foo==bar)
// False (The objects are not the same)
bar = foo;
if(foo==bar)
// True (Now the objects are the same)
一方、equals()メソッドは、2つの変数が同じ状態(値)を持つオブジェクトを参照しているかどうかをテストします。
String foo = new String("abc");
String bar = new String("abc");
if(foo.equals(bar))
// True (The objects are identical but not same)
乾杯:-)
String w1 ="Sarat";
String w2 ="Sarat";
String w3 = new String("Sarat");
System.out.println(w1.hashCode()); //3254818
System.out.println(w2.hashCode()); //3254818
System.out.println(w3.hashCode()); //3254818
System.out.println(System.identityHashCode(w1)); //prints 705927765
System.out.println(System.identityHashCode(w2)); //prints 705927765
System.out.println(System.identityHashCode(w3)); //prints 366712642
if(w1==w2) // (705927765==705927765)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
if(w2==w3) // (705927765==366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints false
if(w2.equals(w3)) // (Content of 705927765== Content of 366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
.equals(...)
比較しようとしているクラスで実装する必要があることを覚えておいてください。そうでなければ、あまり意味がありません。Objectクラスのメソッドのバージョンは、比較演算と同じことをします:Object#equals。
オブジェクトに対して比較演算子を本当に使いたいのは、列挙型を比較するときだけです。これは、Enum値のインスタンスが一度に1つしかないためです。たとえば、列挙型が
enum FooEnum {A, B, C}
あなたはの複数のインスタンスを持つことはありませんA
時、そして同じのためにB
とC
。つまり、実際には次のようなメソッドを記述できます。
public boolean compareFoos(FooEnum x, FooEnum y)
{
return (x == y);
}
そして、あなたは何の問題もありません。
コードを評価すると、(==)がメモリアドレスに従って比較されるのに対して、equals(Object o)はインスタンスのhashCode()を比較することは明らかです。そのため、後で驚きに直面しない場合は、equals()とhashCode()の間の契約を破らないでください。
String s1 = new String("Ali");
String s2 = new String("Veli");
String s3 = new String("Ali");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println("(s1==s2):" + (s1 == s2));
System.out.println("(s1==s3):" + (s1 == s3));
System.out.println("s1.equals(s2):" + (s1.equals(s2)));
System.out.println("s1.equal(s3):" + (s1.equals(s3)));
/*Output
96670
3615852
96670
(s1==s2):false
(s1==s3):false
s1.equals(s2):false
s1.equal(s3):true
*/
ここでの違いのためのルールの一般的な親指でrelational operator ==
とはthe method .equals()
。
object1 == object2
object1とobject2によって参照されるオブジェクトがHeapの同じメモリ位置を参照しているかどうかを比較します。
object1.equals(object2)
メモリ内の場所に関係なく、object1とobject2の値を比較します。
これは、文字列を使用してうまく実証できます
シナリオ1
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = new String("Hello");
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? false
is str1.equals(str2) ? true
シナリオ2
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? true
is str1.equals(str2) ? true
この文字列比較は、他のタイプのオブジェクトを比較するための基礎として使用できます。
たとえば、Personクラスがある場合、 2人を比較する基準となる基準。この人物クラスに、身長と体重のインスタンス変数があるとします。
だから人オブジェクトを作成する person1 and person2
.equals()
、Personをし、これら2つを比較するには、 Person クラスのequalsメソッドをオーバーライドして、比較するインスタンス変数(高さまたは重み)に基づいて定義する必要があります。
しかし、== operator will still return results based on the memory location of the two objects(person1 and person2)
。
この人物オブジェクトの比較を簡単に一般化するために、次のテストクラスを作成しました。これらの概念を実験すると、多くの事実が明らかになります。
package com.tadtab.CS5044;
public class Person {
private double height;
private double weight;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(height);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
/**
* This method uses the height as a means of comparing person objects.
* NOTE: weight is not part of the comparison criteria
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
return false;
return true;
}
public static void main(String[] args) {
Person person1 = new Person();
person1.setHeight(5.50);
person1.setWeight(140.00);
Person person2 = new Person();
person2.setHeight(5.70);
person2.setWeight(160.00);
Person person3 = new Person();
person3 = person2;
Person person4 = new Person();
person4.setHeight(5.70);
Person person5 = new Person();
person5.setWeight(160.00);
System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
System.out.println("is person2 == person3 ? " + (person2 == person3)); // true
//this is because perosn3 and person to refer to the one person object in memory. They are aliases;
System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;
System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;
// even if the person2 and person5 have the same weight, they are not equal.
// it is because their height is different
System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}
}
このクラスの実行結果は次のとおりです。
is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
==演算子の参照は常に比較されます。しかしの場合
equals()メソッド
オーバーライドされたメソッドで指定された実装の基本でオブジェクトを比較するよりも、オーバーライドされたequalsメソッドが実装されているかどうかは、実装に依存しています。
class A
{
int id;
String str;
public A(int id,String str)
{
this.id=id;
this.str=str;
}
public static void main(String arg[])
{
A obj=new A(101,"sam");
A obj1=new A(101,"sam");
obj.equals(obj1)//fasle
obj==obj1 // fasle
}
}
上記のコードでは、objオブジェクトとobj1オブジェクトの両方に同じデータが含まれていますが、参照は同じではないため、equalsはfalseを返し、==も返します。しかし、equalsメソッドをオーバーライドした場合
class A
{
int id;
String str;
public A(int id,String str)
{
this.id=id;
this.str=str;
}
public boolean equals(Object obj)
{
A a1=(A)obj;
return this.id==a1.id;
}
public static void main(String arg[])
{
A obj=new A(101,"sam");
A obj1=new A(101,"sam");
obj.equals(obj1)//true
obj==obj1 // fasle
}
}
私たちがオーバーライドした同じケースでtrueとfalseを返すことを確認してください
等しいメソッド。
オブジェクトのコンテンツ(id)の基本についてオブジェクトを比較します
しかし==
オブジェクトの参照を比較します。
==とequals()の主な違いは
1)==は、プリミティブを比較するために使用されます。
例えば :
String string1 = "Ravi";
String string2 = "Ravi";
String string3 = new String("Ravi");
String string4 = new String("Prakash");
System.out.println(string1 == string2); // true because same reference in string pool
System.out.println(string1 == string3); // false
2)equals()はオブジェクトを比較するために使用されます。例えば :
System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects
System.out.println(string1.equals(string3)); // true
System.out.println(string1.equals(string4)); // false
public class StringPool {
public static void main(String[] args) {
String s1 = "Cat";// will create reference in string pool of heap memory
String s2 = "Cat";
String s3 = new String("Cat");//will create a object in heap memory
// Using == will give us true because same reference in string pool
if (s1 == s2) {
System.out.println("true");
} else {
System.out.println("false");
}
// Using == with reference and Object will give us False
if (s1 == s3) {
System.out.println("true");
} else {
System.out.println("false");
}
// Using .equals method which refers to value
if (s1.equals(s3)) {
System.out.println("true");
} else {
System.out.println("False");
}
}
}
----出力----- true false true
プリミティブ型のラッパーオブジェクト-つまり、Int、Long、Double-==は、2つの値が等しい場合にtrueを返します。
Long a = 10L;
Long b = 10L;
if (a == b) {
System.out.println("Wrapped primitives behave like values");
}
対照的に、上記の2つのLongを2つの別々のArrayListに入れると、equalsはそれらを同じものとして認識しますが、==は認識しません。
ArrayList<Long> c = new ArrayList<>();
ArrayList<Long> d = new ArrayList<>();
c.add(a);
d.add(b);
if (c == d) System.out.println("No way!");
if (c.equals(d)) System.out.println("Yes, this is true.");
Long a = 128l; Long b = 128l; System.out.println(a == b);
文字列プール(別名インターン)と整数プールぼかし、さらに違いは、あなたが使用することを可能にする==
いくつかのケースでは、オブジェクトのための代わりに、.equals
これにより、複雑さが増す代わりに、パフォーマンス(?)が向上します。
例えば:
assert "ab" == "a" + "b";
Integer i = 1;
Integer j = i;
assert i == j;
複雑さのトレードオフ:以下はあなたを驚かせるかもしれません:
assert new String("a") != new String("a");
Integer i = 128;
Integer j = 128;
assert i != j;
そのようなマイクロ最適化から離れて、常に.equals
オブジェクトと==
プリミティブに使用することをお勧めします。
assert (new String("a")).equals(new String("a"));
Integer i = 128;
Integer j = 128;
assert i.equals(j);
つまり、答えは「はい」です。
Javaでは、==
オペレーターは2つのオブジェクトを比較して、それらが同じメモリー位置を指しているかどうかを確認します。一方、.equals()
メソッドは2つのオブジェクトを実際に比較して、それらが同じオブジェクト値を持っているかどうかを確認します。
基本的に、==
2つのオブジェクトがヒープ上で同じ参照を持っているかどうかを比較します。したがって、2つの参照が同じオブジェクトにリンクされていない限り、この比較はfalseになります。
equals()
Object
クラスから継承したメソッドです。このメソッドはデフォルトで、2つのオブジェクトが同じ参照を持つかどうかを比較します。その意味は:
object1.equals(object2)
<=> object1 == object2
ただし、同じクラスの2つのオブジェクト間の等価性を確立する場合は、このメソッドをオーバーライドする必要があります。オーバーライドしたhashCode()
場合は、メソッドをオーバーライドすることも非常に重要ですequals()
。
hashCode()
同等性の確立がJavaオブジェクトコントラクトの一部である場合に実装します。コレクションを使用していて、まだ実装していない場合hashCode()
、奇妙な問題が発生する可能性があります。
HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat, "This is a cool cat");
System.out.println(cats.get(new Cat("molly"));
null
実装していない場合は、前のコードを実行した後に出力されhashCode()
ます。
Javaは演算子のオーバーロードをサポートしていないため、==はすべてのオブジェクトで同じように動作しますが、equals()メソッドはJavaでオーバーライドでき、オブジェクトを比較するロジックはビジネスルールに基づいて変更できます。
Javaでの==とequalsの主な違いは、 "=="はプリミティブの比較に使用されるのに対し、equals()メソッドはオブジェクトの等価性をチェックすることをお勧めします。
文字列比較は、==とequalsメソッドの両方を使用する一般的なシナリオです。java.lang.Stringクラスはequalsメソッドをオーバーライドするため、2つのStringオブジェクトに同じコンテンツが含まれている場合はtrueを返しますが、2つの参照が同じオブジェクトを指している場合は==だけがtrueを返します。
==およびequals()メソッドを使用して、Javaの2つの文字列が等しいかどうかを比較する例を次に示します。これにより、いくつかの疑問が解消されます。
public class TEstT{
public static void main(String[] args) {
String text1 = new String("apple");
String text2 = new String("apple");
//since two strings are different object result should be false
boolean result = text1 == text2;
System.out.println("Comparing two strings with == operator: " + result);
//since strings contains same content , equals() should return true
result = text1.equals(text2);
System.out.println("Comparing two Strings with same content using equals method: " + result);
text2 = text1;
//since both text2 and text1d reference variable are pointing to same object
//"==" should return true
result = (text1 == text2);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);
}
}