In this part of Java programming mistakes, we will take a look at another common pattern, where programmers tend to use the "==" operator to compare Objects, similar to comparing primitives. Since the equality of objects can be very different in the physical and logical sense, and in the case of domain objects, it's mostly driven by business rules, comparing objects with the "==" operator, introduces subtle bugs, which are hard to find. The difference between equals() and == operator, one of the Java classics is also asked to find out if the developer is familiar with this important concept or not.
Using the == operator only makes sense when comparing primitives like int, or final constants like Enum. Though there is more involved in comparing two Enum, which you learn by following that link.
One of the most common patterns of this mistake is comparing two Strings with the == operator, which we will see in this article. By the way, this is the third article in a series of common Java programming mistakes, and if you haven't read the previous two, you can read them here :
Using the == operator only makes sense when comparing primitives like int, or final constants like Enum. Though there is more involved in comparing two Enum, which you learn by following that link.
One of the most common patterns of this mistake is comparing two Strings with the == operator, which we will see in this article. By the way, this is the third article in a series of common Java programming mistakes, and if you haven't read the previous two, you can read them here :
- Java Mistake 1: Using double and Float for monetary Calculation
- Java Mistake 2: Mixing up static and non-static synchronized methods
And, If you are new to the Java world then I also recommend you go through these Java Programming Courses to learn Java in a better and more structured way. This is one of the best and up-to-date courses to learn Java online.
Comparing Strings with == instead of equals() method
Checking if two Strings are equal or not using equality operator (==) and not with equals method is a mistake, mostly seen between fresher or new Java developers. What makes it worst is the fact that String literal if compared with equality operation (==) or not equality operator (!=) behaves perfectly, which makes programmers think that this is the right way of comparing Strings in Java, which in fact is not.
In reality, the "==" operator returns true if both operands point to the same object. In the case of String literal, it’s true because String pool returns the same String object if created as literal, but it breaks when you compare two String that is not in the pool or only one of them is literal.
To avoid this subtle bug, always use the equals() method of String to compare the equality of two String in Java, which returns true if both string objects contain the exact same characters.
You can also see these free websites to learn Java online to learn about both equality operators and how it works with primitive and object types in Java. It is also one of the better books about practical Java programming in the market.
Anyway, here is an example of comparing String which makes this Java mistake clear:
In reality, the "==" operator returns true if both operands point to the same object. In the case of String literal, it’s true because String pool returns the same String object if created as literal, but it breaks when you compare two String that is not in the pool or only one of them is literal.
To avoid this subtle bug, always use the equals() method of String to compare the equality of two String in Java, which returns true if both string objects contain the exact same characters.
You can also see these free websites to learn Java online to learn about both equality operators and how it works with primitive and object types in Java. It is also one of the better books about practical Java programming in the market.
Anyway, here is an example of comparing String which makes this Java mistake clear:
public class UseEqualsToCompareString { public static void main(String args[]) throws IOException { String name = "abc"; String surname = "abc"; //this will return true because name and surname points to same string object if(name == surname){ System.out.println("Two Strings are equal by == because they cached in string pool"); } surname = new String("abc"); //this will result in false as now surname is not a string literal // and points to different object if(name == surname){ System.out.println("String literal and String created with new() are equal using =="); }else{ System.out.println("String literal and String created with new() are not equal using =="); } //both strings are equal because there content is same if(name.equals(surname)){ System.out.println("Two Strings are equal in Java using equals method because content is same"); }else{ System.out.println("Two Strings are not equal in Java using equals method because content is same"); } } } Output: Two Strings are equal by == because they cached in string pool String literal and String created with new() are not equal using == Two Strings are equal in Java using equals method because content is same
So always use the equals() method to compare two strings in Java, that's also the right way to compare Strings in Java. This is also true for comparing an instance of the Integer class in Java 5.
The JDK 5 release, also known as Tiger introduces autoboxing and unboxing which converts int to Integer automatically. the worst part is that autoboxing creates an Integer object by calling the Integer.valueOf() method which maintains an internal Integer cache of default range -128 to 127.
So, anytime you auto box an int value which is from -128 to 127 it will return the same Integer object which if compared with equality operator "==" will return true, but as soon as you moved out of that range autoboxed integer compared with "==" will return false despite having a same numerical value. See here for more details on this subtle issue.
This creates a lot of confusion around Java programmers. The bottom line is to avoid using "==" for comparing objects until you want it explicitly, always use equals() method for checking the equality of two objects.
Btw, If you have come here as part of your Java Interview preparation then you can also check out these Java topics and resources to prepare better and crack in first chance.
Anyway, following Java code example will make these things clear:
The JDK 5 release, also known as Tiger introduces autoboxing and unboxing which converts int to Integer automatically. the worst part is that autoboxing creates an Integer object by calling the Integer.valueOf() method which maintains an internal Integer cache of default range -128 to 127.
So, anytime you auto box an int value which is from -128 to 127 it will return the same Integer object which if compared with equality operator "==" will return true, but as soon as you moved out of that range autoboxed integer compared with "==" will return false despite having a same numerical value. See here for more details on this subtle issue.
This creates a lot of confusion around Java programmers. The bottom line is to avoid using "==" for comparing objects until you want it explicitly, always use equals() method for checking the equality of two objects.
Btw, If you have come here as part of your Java Interview preparation then you can also check out these Java topics and resources to prepare better and crack in first chance.
Anyway, following Java code example will make these things clear:
public class IntegerAutoBoxingTest { public static void main(String args[]) throws IOException { Integer number1 = 12; Integer number2 = 12; //two integers will be equal because Java maintains cache // of Integers for values -128 to 128 if(number1 == number2){ System.out.println("Two Integers objects are equal with == because they created " + "using auto boxing and there value is between -128 to 128"); } number1 = new Integer(12); //two integers will not be equal because one new Integer() creates separate object if(number1 == number2){ System.out.println("Integer created using auto-boxing and created using new() " + "are equal using == "); }else{ System.out.println("Integer created using auto-boxing and crated using new() " + "are not equal using == "); } //both Integers will be equals because there numeric value is same if(number1.equals(number2)){ System.out.println("Two Integers in Java are equal using equals method " + "because of same numeric value"); }else{ System.out.println("Integers in Java are not equal using equals method"); } number1 = 150; number2 = 150; //Integers will not be equal as there are out of cache range -128 and 128. if(number1 == number2){ System.out.println("Two Integer objects created with auto boxing with value " + "outside -128 to 128 are equal using == "); }else{ System.out.println("Two Integer objects created with auto boxing with value " + "outside -128 to 128 are not equal using == "); } } }
That's all on this part of common Java mistakes. Remember, always prefer the equals() method over == operator for checking the object’s equality. Let us know if you like this series and have any other common Java mistakes or patterns, which you would like to share with the Java community.
Good Information
ReplyDeleteVery nice explanation...
ReplyDeleteOne small correction In the program its mentioned as "outside -128 to 128 are equal using =="
Please correct the positive range to 127
@Mutturaj, good catch, thanks for pointing it out. I agree it should be -128 to 127, the range of byte in Java.
ReplyDeleteI do like this serie, and would like to see more posts on common java mistakes.
ReplyDeleteGood Information. One point to add here that for Object class, equals method implementation is same as comparing "==" and leftover to its sub-class (String, Integer or any class) to define how would it like to be compared to be equal (For String its exact unicode char and for Integer its the number comparison).
ReplyDelete@Gupta, yes you are right, it's individual class' responsibility to define the equality. So, if you create a domain object, you must provide equals(), hashcode() and compareTo(). They are very useful, also equals() and compareTo() should return 1 for equal objects.
ReplyDelete