3

以下のコードをご覧ください

class TestToString 
{
  public static void main(String args[]) 
  {
    CheckToString cs = new CheckToString (2);
    CheckToString c = new CheckToString (2);
    if( cs.equals(c))
       System.out.println(" Both objects are equal");
    else
       System.out.println(" Unequal objects ");
  }
}

class CheckToString 
{
   int i;
   CheckToString () 
   {
      i=10;
   }
   CheckToString (int a) 
   {
     this.i=a;
   }
}

出力: 等しくないオブジェクト

しかし、私は出力が

両方のオブジェクトが等しい

両方のオブジェクトが異なる参照を持っていることを理解しました。

System.out.println(cs); //com.sample.personal.checkToString@19821f
System.out.println(c); //com.sample.personal.checkToString@addbf1

しかし、私は尋ねていました、なぜそれらは異なる参照を持っているのですか? 一方、以下のケースでは、オブジェクトは同じメモリ位置を持っています。

Integer a = new Integer(2);
Integer b = new Integer(2);
System.out.println(a);           //2
System.out.println(b);           //2

ユーザー定義クラスのオブジェクトと定義済みクラスのオブジェクトを比較しています。ユーザー定義クラスのオブジェクトは、-128 から 127 を超える値を持つ整数クラスのオブジェクトと同じように動作するようです。なぜ両方のケースで参照が異なるのですか? (-128~127の値を持つIntegerクラスも同様、ユーザー定義クラスは別)

4

5 に答える 5

7

equalsチェック参照のデフォルトの実装。メモリ内で同じものを参照しない 2 つの異なるオブジェクトを作成しています。

equals の適切な実装は次のようになります。

public boolean equals(Object o) {
  if (!(o instanceof CheckToString)) {
    return false;
  }
  CheckToString other = (CheckToString) o;
  return i == other.i;
}

をオーバーライドするときは、 もequalsオーバーライドする必要がありますhashCode

と言うときはいつでもnew CheckToString()、メモリ内に新しいオブジェクトを作成しているので、別の とはまったく異なる参照ですnew CheckToString()。オブジェクト定義の中に何があるかは問題ではありません。

あなたがIntegerについて言及したことは真実ですがInteger、あなたが作成したカスタムオブジェクトではなく、に適用されます。

于 2012-10-19T10:31:51.713 に答える
3

クラスでequalsメソッドをオーバーライドする必要があります。CheckToString

@Override
public boolean equals(Object o){
   if(this==o){
      return true;
   }
   if(o instanceof CheckString){
       CheckString other = (CheckString) o;
       return this.i == other.i;
   }
   return false;
}

equalsオーバーライドするときにもオーバーライドすることをお勧めしますhashCode。これにより、ハッシュされたコレクション (つまり、HasSet、LinkedHasSet、HashMap) でオブジェクトを使用できるようになります。このような場合、クラスはプリミティブ整数のラッパーのように見えるため、整数自体を返すことができると思います。

@Override
public int hashCode(){
   return i;
}

そして最後に、toStringクラスのインスタンスを見るたびに、オブジェクトのわかりやすい、人間が読める表現が表示されるように、オーバーライドすることを常にお勧めします。

@Override
public String toString(){
   StringBuilder sb = new StringBuilder();
   sb.append(this.getClass().getSimpleName()).append("[");
   sb.append("i: ").append(i).append("]");
   return sb.toString();
}
于 2012-10-19T10:39:18.117 に答える
0

2 つのオブジェクトが同じメモリ位置を指していないことは明らかです (オブジェクト参照を比較していることに注意してください)。詳細については、オブジェクト クラスのJavaDocequals()とそれぞれのメソッドを参照してください。

文字列表現を比較するには、次の変更を行うことができます。

class TestToString
 {
  public static void main(String args[])
   {
    CheckToString cs = new CheckToString(2);
    CheckToString c = new CheckToString(2);
    if( cs.toString().equalsIgnoreCase(c.toString()))
       System.out.println(" Both objects are equal");
    else
       System.out.println(" Unequal objects ");
 }
}


class CheckToString
{
   int i;
   CheckToString()
   {
      i=10;
   }
   CheckToString(int a)
   {
     this.i=a;
   }
   public String toString(){
    return String.valueOf(i);
   }
}

ps: オブジェクトのケースの変更にも注意してください ( Java 規則)

于 2012-10-19T10:37:55.500 に答える
-1

デフォルトでは、equals メソッドは任意の 2 つのオブジェクトのハッシュコードのみをチェックします。そのため、オブジェクトの基になるプロパティに応じて equals メソッドが結果を返す必要がある場合は、それに応じて equals メソッドをオーバーライドする必要があります。

于 2012-10-19T10:32:34.407 に答える