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 之间的整数类相同,对于用户定义的类不同)

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 个对象显然没有指向同一个内存位置(请注意,您正在比较对象引用)。有关更多信息,请参阅Object Class 的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 方法基于引用进行比较,但是如果您覆盖当前类中的 equals 方法,则它是基于内容进行比较...但在 java.lang.StringClass 中,它是比较内容的基础

于 2014-08-13T17:19:04.993 回答
-1

默认情况下,equals 方法只检查任意两个对象的哈希码。因此,如果您需要 equals 方法根据对象中的任何底层属性返回结果,则必须相应地覆盖 equals 方法。

于 2012-10-19T10:32:34.407 回答