.equals and == method

Hi,

I read as below

.equals() method present in object class also meant for reference comparison only based on our requirement we can override for content comparison.(i thought == do reference comparison not .equals() method???)
In String class, all wrapper class and all collection classes .equals() method is overridden for content comparison.

String s1= new String("john")
String s2= new String("john")////as attached in picture. So by not seeing picture, we cannot say both s1, s2 refer to same john object or different john object(which is case here)??



String s3= new String("mike")
String s4= new String("mike")//as attached in picture. So by not seeing picture we cannot say both s3, s4 refer to same mike object(which is case here) or different mike object??



s3==s4 is true since both refer to same object.(since both refer to same object obviously content is same right. so by default in case of String if == is true then .equals() always true right??
Does this behaviour change with StringBuilder, Custom Object, string Buffer etc


please advise
--.png
LVL 7
gudii9Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Éric MoreauSenior .Net ConsultantCommented:
string has a special implementation. You don't have to use "new" and it will work correctly (string s2="mike";).

For other objects, when you are using =, the pointer (or reference) to the objects is being compared. If they are the same, True is returned. Because you can override the Equals, you can write code in it to compare the values of your objects being compared instead of the pointer.
0
Éric MoreauSenior .Net ConsultantCommented:
And for StringBuilder, you should compare the result of the .ToString() to see if they have the same content.
0
gudii9Author Commented:
please find complete attachment
--.png
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

ozoCommented:
The picture illustrates s1 and s2 referring to different objects with the same content, and
s3 and s4 referring to the same object (which will therefore have the same content)
0
Éric MoreauSenior .Net ConsultantCommented:
if s1 and s2 are string, the == operator has been overridden to check the content instead of the reference. If s1 and s2 are your own objects for which you haven't overridden the == operator, they will not match since they have different pointers.

See http://www.codeproject.com/Articles/178309/Operator-Overloading-in-C-NET for an example of how to override operators.
0
gudii9Author Commented:
if s1 and s2 are string, the == operator has been overridden to check the content instead of the reference.

i thought other way from these links

http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#equals-java.lang.Object-
http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-



if s1 and s2 are string, the .equals() operator will only check references not the content. please correct me if i am wrong
0
gudii9Author Commented:
The picture illustrates s1 and s2 referring to different objects with the same content, and
s3 and s4 referring to the same object (which will therefore have the same content)

public class EqualsEx {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s1 = "xyz";
		String s2 = "xyz";
		
		String s3 = "abc";
		String s4 = null;
		s4=s3;
		
		System.out.printf("s1.equals(s2): %b%ns1 == s2: %b%n",
		                s1.equals(s2), s1 == s2);
		
		
		System.out.printf("s3.equals(s4): %b%ns3 == s4: %b%n",
                s3.equals(s4), s3 == s4);
	}

}

Open in new window



s1.equals(s2): true
s1 == s2: true
s3.equals(s4): true
s3 == s4: true

Is above is correct use case for this diagram ??
please advise
0
Éric MoreauSenior .Net ConsultantCommented:
My apologies, I really thought it was .Net!
0
gudii9Author Commented:
The picture illustrates s1 and s2 referring to different objects with the same content,

so it should return true for s1.equals(s2) and it should return s1==s2 as false right.

and
s3 and s4 referring to the same object (which will therefore have the same content)

so it should return true for s3.equals(s4) and it should return s3==s4 as false right?
please advise
0
gudii9Author Commented:
So when Strings come into picture i should blindly avoid == and use only .equals()


Instead of String if i have say Employee object as attached then the behaviour changes right.

Since String checks in the pool if there is already john created in String pool s2 object reference refers to same memory address of the same john object so == returns false in first digram case right.

where as for Employee object s1 and s2 memory references points to different memory address of different john object so == false
--Employee.jpg
0
gudii9Author Commented:
In the case of s3 and s4 string objects since i am assigning s3 reference to s4 reference
both of them point to same memory address of Mike Sting object??



public class EqualsEx {

      /**
       * @param args
       */
      public static void main(String[] args) {
            // TODO Auto-generated method stub
            String s1 = "xyz";
            String s2 = "xyz";
            
            String s3 = "abc";
            String s4 = null;
            s4=s3;
            
            System.out.printf("s1.equals(s2): %b%ns1 == s2: %b%n",
                            s1.equals(s2), s1 == s2);
            
            
            System.out.printf("s3.equals(s4): %b%ns3 == s4: %b%n",
                s3.equals(s4), s3 == s4);
      }

}
0
gudii9Author Commented:
How output differen if code is as below

public class EqualsEx2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Employee s1 =new Employee( "xyz");
			Employee s2 =new Employee( "xyz");
		
		Employee s3 = new Employee( "xyz");;
		Employee s4 = null;
		s4=s3;
		
		System.out.printf("s1.equals(s2): %b%ns1 == s2: %b%n",
		                s1.equals(s2), s1 == s2);
		
		
		System.out.printf("s3.equals(s4): %b%ns3 == s4: %b%n",
                s3.equals(s4), s3 == s4);
	}

}

Open in new window

0
krakatoaCommented:
Let's be straight :  

== (NOT =, which is incorrectly stated here : Éric Moreau2015-05-20 at 11:05:43ID: 40786965)

tests for object reference equality

and .equals() tests for value (payload), equivalence.  There isn't much else to know about this situation.

. . .  and "==" is not a method.)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Éric MoreauSenior .Net ConsultantCommented:
>>== (NOT =, which is incorrectly stated here : Éric Moreau2015-05-20 at 11:05:43ID: 40786965)

I already told that I was answering with .Net in mind!
0
krakatoaCommented:
Point taken. My concern is only for the OP. I didn't realise that == is overridden in Java. Learn something every day.
0
gudii9Author Commented:
Point taken. My concern is only for the OP. I didn't realise that == is overridden in Java. Learn something every day.

learn lot of things everyday for me in java



tests for object reference equality

and .equals() tests for value (payload), equivalence.  There isn't much else to know about this situation.

. . .  and "==" is not a method.)

more precisely == tests for object references(my mind thinks s1 and s2 are reference and they are always different no matter what) pointing memory address  equality right?

Please correct me if i am wrong.

Any one good book which explain these concepts and collection, threads related core java concepts in detail and clear apart from head first java which is bit confusing being different back ground i cannot relate and understand some examples there. please advise
0
gudii9Author Commented:
I am currently reading this paper which i like. It also refers to few other papers specifically on string and HashTable etc
http://javapapers.com/core-java/hashcode-and-equals-methods-override/
0
krakatoaCommented:
learn lot of things everyday for me in java

... and where did you yourself hear about == being overridden can I know?

As for Strings, you only really need to remember that .equals() should be used to compare two Strings. Strings are Charsequences and so all the chars in the String are checked.
0
krakatoaCommented:
My point was - and maybe I should have said so directly - that "==" is NOT overridden. What happens is that if, for Strings, you decide to override .equals(), you must test for equality using "==". There is no such thing as overriding an operator ("==" in this case).

This is why you then need to override hashCode(), because your test for equality no longer looks at the String's contents (its CharSequence), but at its object reference.
0
krakatoaCommented:
. . .  and  you should read this fully :

equals() and ==
0
gudii9Author Commented:
// Create three String objects.
String strA = new String("APPLES");
String strB = new String("APPLES");
String strC = new String("ORANGES");

// Create a String reference and assign an existing String's reference to it
// so that both references point to the same String object in memory.
String strD = strA;

// Print out the results of various equality checks
System.out.println(strA == strB);
System.out.println(strA == strC);
System.out.println(strA == strD);

The output of the code fragment above is:

false
false
true

Look carefully at the output of the first comparison - the result of comparing strA to strB (both of whose values are "APPLES") is false!  This is because the equality operator (==) compares the references (addresses in memory) of the two Strings as two different numbers - this is known as reference equality.  In this case both String objects have the exact same value, i.e., "APPLES" but they are in different physical memory locations so their references (addresses in memory) are different and the result is false.

The second comparison between strA and strC also returns false as one would expect when comparing "APPLES" and "ORANGES" but not because the characters in the two String objects are different.  Rather, it is because the references of the two different String objects are different addresses and, therefore, not numerically equal.  Very subtle - depending on the quality of your tests you may or may not notice this kind of logical error in your own code.

The third comparison compares the reference value strA to strD.  In this case strD was assigned the reference (memory address) of strA so both strA and strD are the same reference (memory location) value and the comparsion returns true.

i like this explanation in that link
0
gudii9Author Commented:
Logical equality compares the data of the objects instead of the value of the references.  Examine the following logical equality checks using the same String object references from the example above:

System.out.println(strA.equals(strB));
System.out.println(strA.equals(strC));
System.out.println(strA.equals(strD));

The output from these comparisons is:

true
false
true

These are the outcomes one would typically expect and want.  Notice the use of the equals method instead of the == operator.  The String class overrides the equals method it inherited from the Object class and implemented logic to compare the two String objects character by character.

Why, you might ask, did the String class override the equals method inherited from the Object class?  Because the equals method inherited from Object performs reference equality!  Here is what the implementation of the equals method in Object looks like:

public boolean equals(Object other)
{
   return this == other;
}

The reason the equals method in the Object class does reference equality is because it does not know how to do anything else.   Remember, every class in Java is an Object (via inheritance).  For the Object class's equals method to work correctly for every class (already written or every to be written in the future) it would need knowledge of the future and need to be infinitely large since there are an infinite number of Java classes that can be written - clearly an impossible task!  So, Object's equals method does the best it can without trying too hard - strict reference equality.

i like this too
0
gudii9Author Commented:
How To Override the equals method inherited from the Object class...

When you override any method you must match the method name, return type, and parameter types exactly.  For the equals method, it must be this:

public boolean equals(Object other)
{
   // Logic here to be discuss below...
}

Notice that the parameter type is Object - it must be Object or you will have overloaded equals instead of overriding it.  The errors that can occur when you do this are subtle.  Your code will work correctly much of the time but fail some of the time.  This is due to polymorphism and runtime binding of methods.  The affect is that, depending on the type of the parameter being passed to equals, sometimes your equals method will execute and sometimes the one in Object (performing strict reference equality) will be execute which, you recall, performs reference equality not logical equality.

The next issue is that any referent can be null.  If you use a null reference you will get a NullPointerException - not good.  So, before you can use the parameter passed to equals you must verify that it is not null and, if it is, return false. This makes sense since something (this) cannot be equal to nothing (null).

public boolean equals(Object other)
{
   if (other == null)
   {
      return false;
   }

   // More logic here to be discuss below...
}

Open in new window


i like this too
0
gudii9Author Commented:
public boolean equals(Object other)
{
   if (other == null)
   {
      return false;
   }

   if (this.getClass() != other.getClass())
   {
      return false;
   }

   // More logic here to be discuss below...
}

The getClass method (use above) is one of the methods of the Object class and is inherited by all classes from Object.  It returns a reference to the Class class for the class-type of the reference it is called on. There is only one Class class reference for a particular Class - this is known as a singleton.  All instances of the same Class share the same Class class reference.  If you call getClass on any two references of the same type you'll get the same Class class reference value.  This is one of the rare instance were reference equality (or inequality) is what you want so you do not need to call the equals method of the Class class to compare them (you may, it will work, but it is slightly less efficient and demonstrates lack of understanding).

like this too
0
gudii9Author Commented:
Finally, after determining that the reference passed in (other) is not null and is the same as this, you typically check that all of the instance variables of each object are equal.  This is not a strict requirement - just typical.  When you write a class you decide what equality means and implement it as such. Remember that for primitive instance variable you may use the equality operators (== and !=) unless, of course, they are floats or doubles, in which case you have to decide what level of precision you want/need.  For instance variables that are object references you must use the equals method of their classes.  Arrays require you to loop through them and do the right thing or use methods of the Java Standard Library that implement loops and do the right thing.  For example, lets assume a class called Simple that has two instance variables, an int called x and a String called str.  Assuming that str could never be null (a class invariant you must maintain in the rest of the code belonging to the class) here is what a correct equals method might look like:

public boolean equals(Object other)
{
   if (other == null)
   {
      return false;
   }

   if (this.getClass() != other.getClass())
   {
      return false;
   }

   if (this.x != ((Simple)other).x)
   {
      return false;
   }

   if (!this.str.equals(((Simple)other).str))
   {
      return false;
   }

   return true;
}

Notice that the use of this in the example above in not necessary and included for clarity only.  Also notice that there are many ways to write the code above that are logically equivalent .  You may write your equals methods in any logically equivalent manner you wish.

i did not understand what is 'other' they are talking in the above code? please advise
0
gudii9Author Commented:
Inheritance and the equals Method...

When overriding the equals method in classes making use of inheritance it is important to keep the super class and sub-class as loosely coupled as possible.  Loosely coupled classes make as few assumptions about each other as possible making the code more maintainable over time.  A secondary goal is to avoid duplication of code.  Let's take a look at an example involving three classes, A, B, and C as follows:

public class A
{
   // Class implementation not shown
}

public class B extends A
{
   // Class implementation not shown
}

public class C extends B
{
   // Class implementation not shown
}

As you can see, class A is a sub-class of Object by implicit extension, B is a sub-class of A by explicit extension, and C is a sub-class of B by explicit extension.  Now look at some code making use of some class C objects and checking to see if two objects are equal:

C c1, c2;
c1 = getSomeRandomCObject();
c2 = getSomeRandomCObject();

if (c1.equals(c2))
{
   // Do something, anything, it is not germane to the discussion
}

When class C overrides the equals method it must check that the object reference passes in is not null, that it is the same class (not a requirement, but typical), and that all the instance data is equal - including all superclass instance variables it inherited.  Assuming all C's superclasses maintain strict encapsulation (private instance variables) this presents a problem: How do you access the private instance variables of your superclasses?  One solution would be to use the accessor methods (get-methods) to obtain the data of the super classes - this is an example of tight coupling - a  bad idea!  First, this requires detailed knowledge of the super classes - the sub-class must know all instance data and all methods to access them. The downside of this approach is that it is more work and more likely to be wrong in the first place, and less likely to be maintained properly in the second place.  Imagine someone else wrote class A and you are simply extending it.  By calling the accessor methods of class A in class C's implementation of equals the Class C code is tightly coupled to Class A's implementation.  Now imagine that the person that wrote class A makes changes - how likely are they to realize that class C may be affected by the changes?  Even if they notice will they know how to modify Class C's implementation to work with the new class A?  As you can see, even a relatively simple change to Class A that should be isolated has now become more complicated and error prone.

How do you solve this issue?  You reuse your superclass's implementation of equals when you override equals in your class as follows:

public class C extends B
{
   // Class implementation not shown except for equals

   public boolean equals(Object other)
   {
      if (!super.equals(other))
      {
         return false;
      }

      // Rest of equals method here, i.e., check all class C instance variables for equality
   }
}

Notice the absence of the null-check and class-type check that was stressed earlier in this document.  If you do them here your code will be logically correct but you will be duplicating logic, wasting CPU cycles, and contributing to global-warming - all unnecessary evils.  To see why lets lets follow the flow-of-execution.  The super.equals(other) call in the first line of C's equals method calls its super class's implementation of equals, specifically class B's equals method, which should also call its super.equals in its first line as follows:

public class B extends A
{
   // Class implementation not shown except for equals

   public boolean equals(Object other)
   {
      if (!super.equals(other))
      {
         return false;
      }

      // Rest of equals method here, i.e., check all class B instance variables for equality
   }
}

This super.equals call in class B's equals method calls class A's equals method and class A's equals method looks like this:

public class A
{
   // Class implementation not shown except for equals

   public boolean equals(Object other)
   {
      if (other == null)
      {
         return false;
      }

      if (this.getClass() != other.getClass())
      {
         return false;
      }

      // Rest of equals method here, i.e., check all class A instance variables for equality
   }
}

Remember that class A's super class is, implcitly, Object.  Notice that A's equals does not call super.equals.  This is because Object's equals does reference equality and the entire reason we are overriding equals is to get logical equality instead of reference equality.  Also notice that if we do the null-check first in the most-super-class-prior-to-Object then none of its sub-classes needs to do it directly since it is done via the super.equals call and is done before the reference is used thereby avoiding any possibility of a NullPointerException.  Likewise, the class-type check can be done in the most-super-class-prior-to-Object and reused by the sub-classes via the super.equals call.  Now the classes are loosely coupled - meaning they can change their implementations without affecting the implementation of any sub-class or super class!

in above i have not undersatand loose and tight coupling what author is talking about. Please advise
0
gudii9Author Commented:
Likewise, the class-type check can be done in the most-super-class-prior-to-Object and reused by the sub-classes via the super.equals call.  Now the classes are loosely coupled - meaning they can change their implementations without affecting the implementation of any sub-class or super class!

Not clear on last 2 lines as well. please advise
0
krakatoaCommented:
I (we no doubt) are pleased that you liked the explanations quoted.

As to your last post, the 'other' is the Object "other", passed in to the equals() method.
0
krakatoaCommented:
Means they can implement it again themselves, or call the super method.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.