web-dev-qa-db-ja.com

Javaにおける==とequals()の違いは何ですか?

これを正しく理解したかどうかを明確にしたかったのです。

  • == - >は参照比較です。つまり、両方のオブジェクトは同じメモリ位置を指します。
  • .equals() - >オブジェクト内の値の比較を評価します

私の理解は正しいですか?

554
brainydexter

一般的に、あなたの質問に対する答えは「はい」ですが、...

  • .equals(...)は、それが比較するために書かれたものだけを比較し、それ以上でもそれ以下でもありません。
  • クラスがequalsメソッドをオーバーライドしない場合、デフォルトでは、このメソッドをオーバーライドした最も近い親クラスのequals(Object o)メソッドになります。
  • 親クラスがオーバーライドを提供していない場合、デフォルトでは最終的な親クラスであるObjectのメソッドが使用されるため、Object#equals(Object o)メソッドが残ります。オブジェクトAPIごとに、これは==と同じです。つまり、trueを返しますif and only if両方の変数が同じオブジェクトを参照している(参照が同一である場合)。したがって、機能的同等性ではなくオブジェクトの同等性をテストします。
  • 「契約を破らない」ようにhashCodeをオーバーライドする場合は、必ずequalsをオーバーライドすることを忘れないでください。 APIに従って、2つのオブジェクトのhashCode()メソッドから返される結果mustは、それらのequalsメソッドが同等であることを示す場合、同じです。逆はnot必ずしも真です。

Stringクラスに関して:

Equals() method は、2つのオブジェクト参照が同じStringインスタンスを参照しているかどうかに関係なく、Stringインスタンス内(ヒープ上)の「値」を比較します。 String型の任意の2つのオブジェクト参照が同じStringインスタンスを参照する場合、それは素晴らしいことです。 2つのオブジェクト参照が2つの異なるStringインスタンスを参照していても、違いはありません。比較されている各Stringインスタンス内の「値」(つまり、文字配列の内容)です。

一方、 "==" 演算子 は、 2つのオブジェクト参照 の値を比較して、それらが同じ Stringインスタンス を参照しているかどうかを確認します。両方のオブジェクト参照の値が同じStringインスタンスを「参照」している場合、ブール式の結果は「true」になります。一方、両方のオブジェクト参照の値が「参照」 異なるStringインスタンス である場合(両方のStringインスタンスが同じ「値」を持つ場合でも、つまり各Stringの文字配列の内容インスタンスは同じです)ブール式の結果は "false"になります。

他の説明と同様に、それを沈めましょう。

私はこれが物事を少しクリアすることを願っています。

98

「プリミティブ」と「オブジェクト型」のどちらを使用しているかによって、多少の違いがあります。 「静的」または「非静的」メンバーについて話している場合も同じことが言えます。あなたはまた、上記のすべてを混在させることができます...

これは例です(あなたはそれを実行することができます):

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クラスのメソッド)の説明を比較できます。

54
Almir Campos

==とequalsの違いは、私がそれをよく見ることにするまでしばらくの間私を混乱させました。彼らの多くは、文字列を比較するためには==ではなくequalsを使うべきだと言っています。この答えを願って私は違いを言うことができるでしょう。

この質問に答える最善の方法は、自分自身にいくつか質問をすることです。それでは始めましょう:

以下のプログラムの出力は何ですか?

String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);

あなたが言うなら、

false
true

私はあなたがrightだと言うでしょう - しかし なぜあなたはそれを言ったのですか ?そして、あなたが出力が言うならば、

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行の出力について考えてみてください。私はideoneを使ってこれを印刷しました( ここでコードを確認できます ):

false
true
true
false
mango mango
false
true
17225372
17225372
5433634

ああ! identityHashCode(mango)はidentityHashCode(mango2)と同じですが、identityHashCode(mango3)と同じではありません

すべての文字列変数 - mango、mango2、およびmango3 - が 同じ 値、つまり "mango"を持っていても、identityHashCode()はすべての人にとって同じではありません。

この行// mango2 = "mang";のコメントを外してもう一度実行してみてください。今度は3つのidentityHashCode()がすべて異なることがわかります。うーん、役に立つヒントです

hashcode(x)=Nhashcode(y)=N => x is equal to yの場合

Javaが内部でどのように機能するのかはわかりませんが、私が言ったときにこれが起こったと思います。

mango = "mango";

Javaは、変数mangoによって示される(参照される)文字列"mango"を作成しました。

mango ----> "mango"

私が言ったときに今次の行に:

mango2 = "mango";

これは実際には同じ文字列"mango"を再利用しており、これは次のようになります。

mango ----> "mango" <---- mango2

マンゴーとマンゴー2の両方が同じ参照を指している

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()が成功するテストケースを生成したいと思いました。私が間違っているならば、コメントして私に知らせてください。

41
govindpatel

== 演算子は、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)

乾杯:-)

29
dheeran

カスタムクラスでこれを使用するには、equals関数を(他の関数と共に)オーバーライドする必要があります。

Equalsメソッドはオブジェクトを比較します。

==二項演算子はメモリアドレスを比較します。

12
Andrew Carr

.equals()をオーバーライドしない場合、==と.equals()の両方が同じオブジェクトを参照します。

.equals()をオーバーライドしたら、あなたのやりたいことがその願いです。呼び出し元のオブジェクトの状態と渡されたオブジェクトの状態を比較することも、単にsuper.equals()を呼び出すこともできます。

7
tintin

==演算子:

==は、2つのオペランドを比較するために使用されるJavaの関係演算子です。 2つのオペランドが等しいかどうかを判断するために使用されます。 ==演算子を使用すると、int、char、float、Booleansなどの任意のプリミティブ型を比較できます。比較後、==演算子はブール値を返します。 2つのオペランドが等しい場合、==演算子は真の値を返します。ただし、2つのオペランドが等しくない場合は、偽の値が返されます。オブジェクトと共に使用すると、==演算子は2つのオブジェクト参照を比較し、それらが同じインスタンスを参照しているかどうかを判断します。

.equals()メソッド

equals()は、Stringクラスで使用可能なメソッドで、2つのストリングを比較してそれらが等しいかどうかを判別するために使用されます。このメソッドは、比較の結果としてブール値を返します。 2つの文字列が同じ順序で同じ文字を含んでいる場合、equals()メソッドはtrueを返します。それ以外の場合は、false値を返します。

== 演算子 equals() method です。

演算子は一般的に primitive typeの比較に使われるので、==はメモリアドレスの比較に使われ、equals()メソッドは objects の比較に使われます。

5
ayniam

.equals(...)は、比較しようとしているクラスによって実装される必要があることを忘れないでください。それ以外の場合は、あまり意味がありません。 Objectクラスのメソッドのバージョンは、比較操作と同じ処理を行います。 Object#equals

あなたが本当にオブジェクトのために比較演算子を使いたいと思う唯一の時は、あなたがEnumを比較していることに気づいています。これは、Enum値のインスタンスは一度に1つしか存在しないためです。たとえば、列挙型を考えると

enum FooEnum {A, B, C}

一度に複数のAのインスタンスを持つことはありません。BCについても同じです。つまり、実際には次のようなメソッドを書くことができます。

public boolean compareFoos(FooEnum x, FooEnum y)
{
    return (x == y);
}

そして、あなたは何の問題もないでしょう。

5
fruchtose
 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
5
Sarat Chandra

==と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
3
Ravi Patel

また、.equals()には通常テスト用の==が含まれていることに注意してください。これは、2つのオブジェクトが等しいかどうかをテストしたい場合に最初にテストしたいことです。

そして==は実際にはプリミティブ型の値を調べます。オブジェクトの場合は参照をチェックします。

3
bfs

コードを評価すると、(==)がメモリアドレスに従って比較され、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
    */
3
huseyin
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 true

2
Aamir M Meman

ここに、relational operator ==the method .equals()の違いの一般的なルールを示します

object1 == object2は、object1とobject2によって参照されるオブジェクトがtを参照しているかどうかを比較しますヒープ内の同じメモリ位置

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()を使用してこれら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
2
tadtab

2つの値が等しい場合、プリミティブ型のラッパーオブジェクト、つまりInt、Long、Double - ==がtrueを返すことを追加する価値があります。

Long a = 10L;
Long b = 10L;

if (a == b) {
    System.out.println("Wrapped primitives behave like values");
}

対照的に、上記の2つのLongを2つの別々のArrayListsに入れると、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.");
2
Elroch

==は多くのオブジェクト型で使用できますが、任意の型、特に文字列とGoogle Map MarkersにObject.equalsを使用できます。

2
Dearwolves

==演算子は常に参照が比較されます。しかしの場合

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)の基本でオブジェクトを比較する

しかし==

それでもオブジェクトの参照を比較します。

2
Sachin Jadhav

Javaは演算子のオーバーロードをサポートしていないため、==はすべてのオブジェクトに対して同じ動作をしますが、equals()メソッドはJavaでオーバーライドでき、ビジネスルールに基づいてオブジェクトを比較するロジックを変更できます。

Javaにおける==とequalsの主な違いは、 "=="はプリミティブの比較に使用されるのに対し、equals()メソッドはオブジェクトの等価性をチェックするために推奨されることです。

文字列比較は==とequalsメソッドの両方を使用する一般的なシナリオです。 Java.lang.Stringクラスはequalsメソッドをオーバーライドするため、2つのStringオブジェクトに同じコンテンツが含まれる場合はtrue 2つの参照が同じオブジェクトを指しています。

==とequals()メソッドを使用して、Javaで2つのStringが等しいかどうかを比較するこれは例です

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);

}
}
0
Mike Clark

つまり、答えは「はい」です。

Javaでは、==演算子は2つのオブジェクトを比較して、それらが同じメモリ位置を指しているかどうかを確認します。 .equals()メソッドは実際には2つのオブジェクトを比較して、それらが同じオブジェクト値を持っているかどうかを確認します。

0
JamesOstmann

基本的に、2つのオブジェクトがヒープ上で同じ参照を持つ場合、==は比較します。そのため、2つの参照が同じオブジェクトにリンクされていない限り、この比較はfalseになります。

equals()Objectclassから継承したメソッドです。このメソッドはデフォルトで、2つのオブジェクトが同じ参照を持っているかどうかを比較します。その意味は:

object1.equals(object2) <=> object1 == object2

ただし、同じクラスの2つのオブジェクト間で同等性を確立したい場合は、このメソッドをオーバーライドする必要があります。 hashCode()をオーバーライドした場合は、メソッドequals()をオーバーライドすることも非常に重要です。

同等性を確立することがJava Object Contractの一部であるときにhashCode()を実装します。もしあなたがコレクションを使っていて、hashCode()を実装していないのなら、Strange Bad Thingsが起こるかもしれません:

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"));

hashCode()を実装していない場合は、前のコードを実行した後にnullが表示されます。

0
lmiguelvargasf

String pool (別名 interning )および Integer poolは、違いをさらにぼかし、場合によっては==の代わりに.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;

このようなマイクロ最適化はやめ、alwaysはオブジェクトには.equalsを、そしてプリミティブには==を使用することをお勧めします。

assert (new String("a")).equals(new String("a"));

Integer i = 128;
Integer j = 128;
assert i.equals(j);