Difference between equals method and == operator in java - How to compare Strings in java - testing with String, StringBuffer and Integer



Contents of page :
  • == operator
    • Let’s test == operator with String Object >
    • Why s1==s2 returns false?
    • Let’s test == operator with String Object (when two references are referring to same object) >
    • Why s3==s4 returns true?
  • equals method
    • Let’s test equals method with String Object.
    • Why s1.equals(s2) returns true?
    • Let’s test == operator and equals method with StringBuffer Object >


  • Let’s test == operator with StringBuffer Object >
    • Why sb1==sb2 returns false?
    • Let’s test equals method with StringBuffer Object.
    • Why sb1.equals(sb2) returns false?


  • Additionally, you may enjoy few more experiments using == operator and equals method on String, here i have done few >
  • Summary >

== operator
The == operator checks for referential equality of object, it checks whether two references are referring to same object or not.


Let’s test == operator with String Object >
            String s1 = new String("abc");
            String s2 = new String("abc");
         
            System.out.println(s1==s2); //false


Why s1==s2 returns false?
String s1 = new String("abc");
string is created using new operator, which will force new string to be created in heap (not in string pool).


String s2 = new String("abc");
string is created using new operator, which will force new string to be created in heap (not in string pool).


Hence, s1 and s2 will be the two reference variables referring to different String objects.

Let’s test == operator with String Object (when two references are referring to same object) >
          String s3 = "abc";
          String s4 = "abc";
          System.out.println(s3==s4); //true


Why s3==s4 returns true?
String s3 = "abc";
No string with “abc” is there in pool, so JVM will create string in string pool and s3 will be a reference variable which will refer to it.


String s4 = "abc";
string with “abc” is there in pool, so s4 will be a reference variable which will refer to “abc” in string pool.


Hence, s3 and s4 will be the two reference variables referring to same String object.

equals method
The equals method is defined in java.lang.Object class
By default equals method checks for referential equality (Class may override the method and provide different functionality)
By default  if x == y returns true then equals method also returns true.


Let’s test equals method with String Object.
String class overrides equals method of Object class and compares one string object to the other string object. The result is true if characters in both String object appears in same order.
            String s1 = new String("abc");
            String s2 = new String("abc");
         
            System.out.println(s1.equals(s2)); //true


Why s1.equals(s2) returns true?
Because characters in both String object appears in same order.



Let’s test == operator and equals method with StringBuffer Object >


Let’s test == operator with StringBuffer Object >
          StringBuffer sb1 = new StringBuffer("abc");
          StringBuffer sb2 = new StringBuffer("abc");
         
          System.out.println(sb1==sb2); //false


Why sb1==sb2 returns false?
StringBuffer sb1 = new StringBuffer("abc");
stringBuffer is created using new operator, which will create new StringBuffer object in heap.


StringBuffer sb2 = new StringBuffer("abc");
stringBuffer is created using new operator, which will create new StringBuffer object in heap.


Hence, sb1 and sb2 will be the two reference variables referring to different stringBuffer objects.

Let’s test equals method with StringBuffer Object.
The equals method is defined in java.lang.Object class.
By default equals method checks for referential equality (Class may override the method and provide different functionality).


StringBuffer class doesn’t overrides equals method of Object class. The result is true if both references are referring to same StringBuffer object.
          StringBuffer sb1 = new StringBuffer("abc");
          StringBuffer sb2 = new StringBuffer("abc");
         
          System.out.println(sb1.equals(sb2)); //false


Why sb1.equals(sb2) returns false?
StringBuffer class doesn’t overrides equals method of Object class and the result is false because both references are referring to different StringBuffer object.


Additionally, you may enjoy few more experiments using == operator and equals method on String, here i have done few >
          String s1 = "abc";
          String s2 = "a" + "bc";
          System.out.println(s1 == s2); // true
          System.out.println(s1.equals(s2)); // true

          String s3 = new String("abc");
          String s4 = new String("a") + new String("bc");
          System.out.println(s3 == s4); // false
          System.out.println(s3.equals(s4)); // true

          String x1 = "abc";
          String x2 = new String(new char[] { 'a', 'b', 'c' });
          System.out.println(x1 == x2); // false
          System.out.println(x1.equals(x2)); // true
It’s important to know String are immutable - means any modification made to Sting objects produces new String Object.







Integer >


compare new Integer with new Integer using == operator for comparison >
public class Autoboxing{
   public static void main(String[] args) {
          Integer i1 = new Integer(3);
          Integer i2 = new Integer(3);
          System.out.println(i1 == i2); //false
   }
}
/*output
false
*/


Whenever new operator is used new objects are formed.
As we know, the == operator checks for referential equality of object, it checks whether two references are referring to same object or not, i1 == i2 will always return false.
We must prefer to use equals method for comparing Integer objects i1 and i2 (because Integer class overrides equals method and checks for value rather than referential equality) i1.equals(i2) will return true.
public class Autoboxing_EqualsMethod{
   public static void main(String[] args) {
          Integer i1 = new Integer(3);
          Integer i2 = new Integer(3);
          System.out.println(i1.equals(i2)); // true
   }
}
/*output
true
*/


Tricky part comes when we compare Integer formed without using new operator >
compare Integer with Integer (where both Integers are formed without using new operator) using == operator for comparison >
public class Autoboxing{
   public static void main(String[] args) {
          Integer i1 = 3; //caches Integer object
          Integer i2 = 3; //returns cached Integer object
          System.out.println(i1 == i2); //true
   }
}
/*output
true
*/


Java caching >
Java caches all the Integer objects formed from primitive int values between values -128 to 127 (including -128 and 127). This caching is done in Integer.valueOf method. Hence, Integer.valueOf method returns cached object(if any) for primitive int values between values -128 to 127.  
Note : 127 is just the default value, it’s not the fixed value it can be changed.


Why java do such caching?
  • Java caches the Integer object of most frequently used int values.
  • For optimizing performance.
  • For reducing number of objects formed in heap.


Many java experts have criticized this caching process because it enforces kind of different mechanism for different int values (i.e. for int values not in range of -128 to 127). Example -
Integer i1= 150; //no caching, hence 1st Integer object is formed
Integer i2= 150; //no caching was done, hence 2nd Integer object is formed
When any primitive int value like 150 is used no caching is performed and two Integer objects are formed.

Now, in the above program,
Integer i1 = 3;
3 is autoboxed to Integer (new Integer object is formed) in Integer.valueOf(3) method, new Integer object is cached (as 3 is between -128 to 127) and is referred by Integer i1.


Integer i2 = 3;
Integer.valueOf(3) method returns cached object and now same Integer object is being referred by Integer i1 and i2.
Hence, only one Integer object will be formed in above program.

/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */

Summary >
  • The == operator checks for referential equality of object, it checks whether two references are referring to same object or not.


  • By default equals method checks for referential equality (Class may override the method and provide different functionality)
By default  if x == y returns true then equals method also returns true.
    • String class overrides equals method of Object class and compares one string object to the other string object. The result is true if characters in both String object appears in same order.
    • StringBuffer class doesn’t overrides equals method of Object class. The result is true if both references are referring to same StringBuffer object.




RELATED LINKS>

String pool/ String literal pool/ String constant pool in java

Creating Immutable class in java


No comments:

Post a Comment