3

Please see the below code

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

Output: Unequal objects

But I was expecting the output will be

Both objects are equal

I understood that both the objects have different refferences,

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

but I was asking, why do they have different referrences? whereas in the below case, the objects have same memory locations.

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

I am comparing the object of user-defined class with the object of pre-defined class. It seems the object of user-defined class behaves same as the object of Integer Class having value beyond -128 to 127. Why are the referrences different for both the cases? (same for Integer class having value within -128 to 127 and different for user-defined class)

Jyoti Ranjan
  • 703
  • 2
  • 13
  • 29
  • 5
    Don't scratch eyes! Any class must begin with a capital. Read [Java Code Convention](http://www.oracle.com/technetwork/java/codeconv-138413.html) please – kapandron Oct 19 '12 at 10:34
  • 1
    You should need to learn about equals() method – khan Oct 19 '12 at 10:36
  • Hey, guys , thanks for your response. FYI- I do know Java Convention. I was reading about how .equals() behave and I found this link http://www.coderanch.com/t/409507/java/java/Difference-between-equals ( You can scroll the page to get the same question, but I couldn't find any satisfactory ans. there , so I asked here. So please, focus on what I am asking , not conventions and all. I know, following convention is a good practice. – Jyoti Ranjan Oct 19 '12 at 10:49
  • well, did you go through this? http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#equals%28java.lang.Object%29 – manas Oct 19 '12 at 10:58
  • yes, I went through the link @silent_warrior and edited the question for better clarity of what I am asking. please see the question now. – Jyoti Ranjan Oct 19 '12 at 12:08

5 Answers5

7

The default implementation of equals checks references. You are creating 2 different object, that don't refer the same thing in memory.

A decent implementation of equals would be something like:

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

When overridding equals, you need to override hashCode, too.

Whenever you say new CheckToString(), you are creating a new object in memory, so a totally different reference than another new CheckToString(). It doesn't matter what is inside the object definition.

The stuff you mention about Integer is true, but it applies to Integer, not to a custom object that you have created.

Dan D.
  • 32,246
  • 5
  • 63
  • 79
  • 2
    so basically OP should implement equals. – eis Oct 19 '12 at 10:32
  • I prefer to point the OP in the right direction than giving information that can be searched for in the internet as an answer. – manas Oct 19 '12 at 11:00
  • Indeed. Why don't you go ahead and do that? – Dan D. Oct 19 '12 at 11:33
  • Thanks for the reply, found it useful. Please go through the question again, I have edited it to be more specific regrading what I am asking. Sorry for editing lately. – Jyoti Ranjan Oct 19 '12 at 12:31
3

You need to override the equals method in your CheckToString class:

@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;
}

It's recommended that when you override equals you also override hashCode, so that you can use your object in hashed collections (i.e. HasSet, LinkedHasSet, HashMap). In a case like this, since your class appears to be a wrapper over a primitive integer, I guess you could return the integer itself.

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

And finally, it's always recommended to override toString, so that every time you look at instances of your class you see a friendly, human-readable representation of your object.

@Override
public String toString(){
   StringBuilder sb = new StringBuilder();
   sb.append(this.getClass().getSimpleName()).append("[");
   sb.append("i: ").append(i).append("]");
   return sb.toString();
}
Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • Thanks for the reply, I have gone through your explanation and found it useful. But actually, I was asking, why objects have different referrences for user-defined class whereas they have same reference for Integer class having value in the range of -128 to 127. So, edited the question to make it more specific, Sorry for this. – Jyoti Ranjan Oct 19 '12 at 12:29
  • 1
    @JyotiRanjan The answer to your question is in the [Java Language Specification](http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7), section 5.1.7:Boxing Conversions. It explains that all autobexed integers between -128 and 127 are cached an always return the same instance. This is a performance optimization feature, since boxing is an expensive task. – Edwin Dalorzo Oct 19 '12 at 12:37
  • Ok...thanks..got ur point. Moreover, I have mentioned the diff. Cases regarding .equal and == in my blog...if you are interested, u can see here... http://jyotiranjanpattnaik.wordpress.com/2012/10/19/difference-between-and-equals-in-java/ – Jyoti Ranjan Oct 19 '12 at 14:36
  • 1
    @JyotiRanjan To give profundity to your blog post, you might want to consider altering the size of default cache. You can do that by setting the system property `java.lang.Integer.IntegerCache.high=` in whose case you can make you case #4 in your blog to use the cache. An alternative way to do this with Java HotSpot is to set `-XX:AutoBoxCacheMax=` in whose case you could make autoboxing cache to be used again, even for your case #4. By the way, your blog does not accept comments unless one can login. – Edwin Dalorzo Oct 19 '12 at 15:39
  • 1
    Thanks buddy, that's really a useful info. we can customize the cache size, great! PS:In my blog, for a comment, email and name is mandatory. I don't think it requires registration.(I checked the setting just now) Anyways, thanks for your useful comment. – Jyoti Ranjan Oct 19 '12 at 17:30
0

the 2 objects are obviously not pointing in the same memory location (Notice that you are comparing Object References). For more info see JavaDoc of Object Class and the respective equals() methos

To compare their string representation you could do this modification:

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: Note also the change in the Object's Case (Java Conventions)

MaVRoSCy
  • 17,747
  • 15
  • 82
  • 125
-1

By default, equals method only checks the hashcodes of any two objects. So, if you need that equals method should return result depending on any underlying property in your object, you will have to override equals method accordingly.

Sumit Desai
  • 1,542
  • 9
  • 22
  • 1
    Not the hashcodes - the memory address. In other words, whether or not they're the same instance. – Tom Johnson Oct 19 '12 at 10:34
  • yes...but default implementation of hashcode uses starting address of memory only. – Sumit Desai Oct 19 '12 at 10:35
  • Yes, default equals is based on address, and default hashcode is based on address. That's not quite the same as default equals checking the hashcodes (firstly hashcode may be overridden, secondly in 64-bit JVMs you can have two different objects with the same default hashcode). – Tom Johnson Oct 19 '12 at 10:43
  • 1
    All this is an implementation detail of the HotSpot JVM (and probably other JVMs). Other JVMs are not required to use memory addresses for this matter, so there is no point in discussing it. The point is that the default equals check if two instances are the same, that's all. – Edwin Dalorzo Oct 19 '12 at 10:59
  • @EdwinDalorzo yes, agree with you – Sumit Desai Oct 19 '12 at 11:05
-1

equals method compare on the basis of reference by default in any user define class but if you override the equals method in the current class then it is compare on the basis of content...but in the java.lang.StringClass it is compare on the basis of content always