I constructed a class with one String field. Then I created two objects and I have to compare them using == operator and .equals() too. Here's what I've done:
public class MyClass {
String a;
public MyClass(String ab) {
a = ab;
}
public boolean equals(Object object2) {
if(a == object2) {
return true;
}
else return false;
}
public boolean equals2(Object object2) {
if(a.equals(object2)) {
return true;
}
else return false;
}
public static void main(String[] args) {
MyClass object1 = new MyClass("test");
MyClass object2 = new MyClass("test");
object1.equals(object2);
System.out.println(object1.equals(object2));
object1.equals2(object2);
System.out.println(object1.equals2(object2));
}
}
After compile it shows two times false as a result. Why is it false if the two objects have the same fields - "test"?
== compares object references, it checks to see if the two operands point to the same object (not equivalent objects, the same object).
If you want to compare strings (to see if they contain the same characters), you need to compare the strings using equals.
In your case, if two instances of MyClass really are considered equal if the strings match, then:
public boolean equals(Object object2) {
return object2 instanceof MyClass && a.equals(((MyClass)object2).a);
}
...but usually if you are defining a class, there's more to equivalency than the equivalency of a single field (a in this case).
Side note: If you override equals, you almost always need to override hashCode. As it says in the equals JavaDoc:
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
You should override equals
public boolean equals (Object obj) {
if (this==obj) return true;
if (this == null) return false;
if (this.getClass() != obj.getClass()) return false;
// Class name is Employ & have lastname
Employe emp = (Employee) obj ;
return this.lastname.equals(emp.getlastname());
}
The best way to compare 2 objects is by converting them into json strings and compare the strings, its the easiest solution when dealing with complicated nested objects, fields and/or objects that contain arrays.
sample:
import com.google.gson.Gson;
Object a = // ...;
Object b = //...;
String objectString1 = new Gson().toJson(a);
String objectString2 = new Gson().toJson(b);
if(objectString1.equals(objectString2)){
//do this
}
The overwrite function equals() is wrong.
The object "a" is an instance of the String class and "object2" is an instance of the MyClass class. They are different classes, so the answer is "false".
It looks like equals2 is just calling equals, so it will give the same results.
Your equals2() method always will return the same as equals() !!
Your code with my comments:
public boolean equals2(Object object2) { // equals2 method
if(a.equals(object2)) { // if equals() method returns true
return true; // return true
}
else return false; // if equals() method returns false, also return false
}
The "==" operator returns true only if the two references pointing to the same object in memory. The equals() method on the other hand returns true based on the contents of the object.
Example:
String personalLoan = new String("cheap personal loans");
String homeLoan = new String("cheap personal loans");
//since two strings are different object result should be false
boolean result = personalLoan == homeLoan;
System.out.println("Comparing two strings with == operator: " + result);
//since strings contains same content , equals() should return true
result = personalLoan.equals(homeLoan);
System.out.println("Comparing two Strings with same content using equals method: " + result);
homeLoan = personalLoan;
//since both homeLoan and personalLoan reference variable are pointing to same object
//"==" should return true
result = (personalLoan == homeLoan);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);
Output:
Comparing two strings with == operator: false
Comparing two Strings with same content using equals method: true
Comparing two references pointing to same String with == operator: true
You can also get more details from the link: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1
Statements a == object2 and a.equals(object2) both will always return false because a is a string while object2 is an instance of MyClass
Your implementation must like:
public boolean equals2(Object object2) {
if(a.equals(object2.a)) {
return true;
}
else return false;
}
With this implementation your both methods would work.
If you dont need to customize the default toString() function, another way is to override toString() method, which returns all attributes to be compared. then compare toString() output of two objects. I generated toString() method using IntelliJ IDEA IDE, which includes class name in the string.
public class Greeting {
private String greeting;
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
return this.toString().equals(obj.toString());
}
#Override
public String toString() {
return "Greeting{" +
"greeting='" + greeting + '\'' +
'}';
}
}
Your class might implement the Comparable interface to achieve the same functionality. Your class should implement the compareTo() method declared in the interface.
public class MyClass implements Comparable<MyClass>{
String a;
public MyClass(String ab){
a = ab;
}
// returns an int not a boolean
public int compareTo(MyClass someMyClass){
/* The String class implements a compareTo method, returning a 0
if the two strings are identical, instead of a boolean.
Since 'a' is a string, it has the compareTo method which we call
in MyClass's compareTo method.
*/
return this.a.compareTo(someMyClass.a);
}
public static void main(String[] args){
MyClass object1 = new MyClass("test");
MyClass object2 = new MyClass("test");
if(object1.compareTo(object2) == 0){
System.out.println("true");
}
else{
System.out.println("false");
}
}
}
the return type of object.equals is already boolean.
there's no need to wrap it in a method with branches. so if you want to compare 2 objects simply compare them:
boolean b = objectA.equals(objectB);
b is already either true or false.
When we use == , the Reference of object is compared not the actual objects. We need to override equals method to compare Java Objects.
Some additional information C++ has operator over loading & Java does not provide operator over loading.
Also other possibilities in java are implement Compare Interface .which defines a compareTo method.
Comparator interface is also used compare two objects
Here the output will be false , false beacuse in first sopln statement you are trying to compare a string type varible of Myclass type to the other MyClass type and it will allow because of both are Object type and you have used "==" oprerator which will check the reference variable value holding the actual memory not the actual contnets inside the memory .
In the second sopln also it is the same as you are again calling a.equals(object2) where a is a varible inside object1 . Do let me know your findings on this .
In short, == compares two POINTERS.
If the two pointers are equal, then they both point to same object in memory (which, obviously has the same value as itself).
However, .equals will compare the VALUES of whatever is pointed to, returning true iff they both evaluate to the same value.
Thus, two separate strings (i.e., at different addresses in memory) are always != but are .equal iff they contain the same (null-terminated) sequence of chars.
IN the below code you are calling the overriden method .equals().
public boolean equals2(Object object2) {
if(a.equals(object2)) { // here you are calling the overriden method, that is why you getting false 2 times.
return true;
}
else return false;
}
Related
The following code is a JUnit test function which fails upon execution.
List<KGramPostingsEntry> a = new ArrayList<KGramPostingsEntry>();
List<KGramPostingsEntry> b = new ArrayList<KGramPostingsEntry>();
KGramPostingsEntry entry = new KGramPostingsEntry(1);
a.add(entry);
entry = new KGramPostingsEntry(1);
b.add(entry);
assertTrue(a.containsAll(b));
It uses the KGramPostingsEntry class:
package ir;
public class KGramPostingsEntry {
int tokenID;
public KGramPostingsEntry(int tokenID) {
this.tokenID = tokenID;
}
public KGramPostingsEntry(KGramPostingsEntry other) {
this.tokenID = other.tokenID;
}
public String toString() {
return tokenID + "";
}
public boolean equals(KGramPostingsEntry other) {
if(other.tokenID == this.tokenID) {
return true;
}
return false;
}
}
As you can see, there is an equals() function in the class that compares the tokenID of the different KGramPostingsEntry objects. It seems to me that this function is not used when calling containsAll() in the test. Further experimentation seems to verify this to be true:
List<KGramPostingsEntry> a = new ArrayList<KGramPostingsEntry>();
List<KGramPostingsEntry> b = new ArrayList<KGramPostingsEntry>();
KGramPostingsEntry entry = new KGramPostingsEntry(1);
a.add(entry);
b.add(entry);
assertTrue(a.containsAll(b));
Here, I'm inserting the same object in both lists. This test does not fail. As far as I've gathered, ArrayList makes a copy object of the object sent to add(), before storing a reference to that object. This means that the objects in the two Lists are not the same (even though they have the same tokenID), and that containsAll() does not check for object reference equality. But if it does not check for object reference equality and does not check the equals() function defined in my code, what does it check? The only plausible option to me is that it checks for object value equality, and that the two objects stored in the first test example are somehow different (even though their only property is tokenID, which is the same in both objects).
What is going on here? How can I make this test succeed the way I want it to?
Here the equals declaration of Object:
public boolean equals(Object obj)
(documentation). You're trying to override this method, but instead you overloaded it:
public boolean equals(KGramPostingsEntry other)
Notice how the argument type in your method is KGramPostingsEntry, which differs from the argument type in Object.equals, namely Object. When a method has the same name but different argument types, it is overloaded, not overridden.
When the ArrayList tries to compare its contents with equals, it'll use the most applicable overridden version of Object.equals. That unfortunately doesn't include your method.
Luckily the fix is easy: you need to implement your equals method with an Object argument:
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof KGramPostingsEntry)) {
return false;
}
KGramPostingsEntry other = (KGramPostingsEntry) obj;
if(other.tokenID == this.tokenID) {
return true;
}
return false;
}
The equals method doesn't have the correct signature. It should be
public boolean equals(Object that) {
// ..
}
I had made a program on .equals() in java & having some conceptual problem when I saw some of the online videos on youtube & searched about this thing but not got proper explanation. So guys help me with that thing.
Thanks.
package Practice;
public class StringManipulation11 {
StringManipulation11(String s) {
}
public static void main(String[] args) {
String s = "Good";
String s1 = "Good";
String s2 = "Morning";
String t = new String("Good");
String t1 = new String("Good");
String t2 = new String("Morning");
StringManipulation11 sm = new StringManipulation11("Good");
StringManipulation11 sm1 = new StringManipulation11("Good");
System.out.println(s.equals(s1));// true because check content
System.out.println(s.equals(s2));// false content not match
System.out.println(t.equals(t1));// true because check content
System.out.println(s.equals(t));// true because check content
System.out.println(sm.equals(sm1));// false, but not getting the reason
// why it is false
/*
* In this case also the content is same but not getting the proper
* conclusion why it is false & it is false then why i am getting true
* in "System.out.println(t.equals(t1))" in this condtion.
*/
System.out.println(s.equals(sm));
}
}
In this case, also the content is same but not getting the proper conclusion why it is false & it is false then why I am getting true in System.out.println(t.equals(t1)) in this condition.
The class String has an implementation of equals (and hashcode) which compares the two objects character by character. Your class does not have an implementation of these methods, so it uses the implementation it has inherited from Object, which compares the references, i.e. for it to be true, the instances need to be the same.
That's an important distinction to get your head around, same means these two references are pointing to the exact same instance. And equals means that they are either the same or have equivalent content, but it is up to you to define how the content is compared, see this.
StringManipulation11 is extend object, if you didn't override the equals method the default method is
public boolean equals(Object obj) {
return (this == obj);
}
you can compare the equals method in String
public boolean equals(Object var1) {
if(this == var1) {
return true;
} else {
if(var1 instanceof String) {
String var2 = (String)var1;
int var3 = this.value.length;
if(var3 == var2.value.length) {
char[] var4 = this.value;
char[] var5 = var2.value;
for(int var6 = 0; var3-- != 0; ++var6) {
if(var4[var6] != var5[var6]) {
return false;
}
}
return true;
}
}
return false;
}
}
This is the definition of the equals method in the String class (Java 8):
public boolean equals(Object anObject)
Compares this string to the specified object. The result is true if and only
if the argument is not null and is a String object that represents the same
sequence of characters as this object.
Which means that this method returns true if and only if both Strings represent the same sequence of characters.
In your case you have defined a new class StringManipulation11 which by default uses the equals method of the Object class. And this is its definition:
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x and y
refer to the same object (x == y has the value true).
In your example you have defined two different objects sm and sm1. These variables refer to DIFFERENT objects and this is why the equals method returns false.
According to documentation
assertEquals() Asserts that two objects are equal.
assertSame() Asserts that two objects refer to the same object.
So I am expecting that if I have a class like below
class SomeClass {}
then
SomeClass someClass1= new SomeClass();
SomeClass someClass2= new SomeClass();
assertSame(someClass1,someClass2); // fail
assertEquals(someClass1,someClass2); // fail
the assertEquals should pass and assertSame should fail, as the value of both classes are equal but they have different reference location.
As I get failure in both cases then my question is what are the difference between these two ?
Since you didn't override equals in your class, assertEquals behaves the same as assertSame since the default equals implementation compare references.
150 public boolean equals(Object obj) {
151 return (this == obj);
152 }
If you provide a dumb overriding of equals:
class SomeClass {
#Override
public boolean equals(Object o) {
return true;
}
}
you'll see that assertEquals succeeds.
assertEquals uses equals() method (that you should override in your class to really compare its instances) to compare objects, while assertSame uses == operator to compare them. So the difference is exactly the same as between == (compare by value) and equals (compare identity).
Official JUnit documentation:
assertEquals: Asserts that two objects are equal.
assertSame: Asserts that two objects refer to the same object.
In other words
assertEquals: uses the equals() method, or if no equals() method was overridden, compares the reference between the 2 objects.
assertSame: compares the reference between the 2 objects.
Example 1: equals method was not overridden, so assertSame and assertEquals return the same result, since they compare the objects' reference.
public class A {
private int i;
public A(int i){ this.i = i; }
}
public class TestA {
final A a1 = new A(0);
final A a2 = new A(0);
#Test
public void assertsame_testAssertSame(){
assertSame(a1, a2); // AssertionError: expected:<test2.A#7f13d6e> but was:<test2.A#51cdd8a>
}
#Test
public void assertsame_testAssertEquals(){
assertEquals(a1, a2); // AssertionError: expected:<test2.A#7f13d6e> but was:<test2.A#51cdd8a>
}
}
Example 2: equals method was overridden, so assertSame and assertEquals return the not same result, since the equals method will be used by assertEquals this time.
public class A {
private int i;
public A(int i){ this.i = i; }
#Override
public boolean equals(Object o){
// self check
if(this == o){ return true; } else
// null check
if(o == null){ return false;} else
// type check and cast
if(getClass() != o.getClass()){ return false; } else {
final A a = (A) o;
// field comparison
return Objects.equals(a, a);
}
}
}
public class TestA {
final A a1 = new A(0);
final A a2 = new A(0);
#Test
public void assertsame_testAssertSame(){
assertSame(a1, a2); // AssertionError: expected:<test2.A#7f13d6e> but was:<test2.A#51cdd8a>
}
#Test
public void assertsame_testAssertEquals(){
assertEquals(a1, a2); // OK
}
}
assertEquals: ==
assertSame: ===
'same' matches the type along with the value which is the same as '==='.
The first assert fails because someClass1 and sameClass2 are not the same instances. The second assert fails because equals(Object) method hasn't been defined in SomeClass and its super equals(Object) does reference equality. Since two different instances are compared for equality, this one fails for the same reason as the first.
assertEquals - It check the objects are equal or not based on the overridded equals() method of that class. So we can check the equality of object based on their state(compare the values of their instance variables).
assertEquals()
The assertEquals() method compares two objects for equality, using their equals() method.
#Test
public void assertEquals_example() {
Employee employeeNew = new Employee();
employee.setSalary(1000000.0);
assertEquals("EMPLOYEE OBJECT", employee, employeeNew);
}
If the two objects are equal according to there implementation of their equals() method, the assertEquals() method will return normally. Otherwise, the assertEquals() method will throw an exception, and the test will stop there.
assertSame() and assertNotSame()
The assertSame() and assertNotSame() methods tests if two object references point to the same object or not. It is not enough that the two objects pointed to are equals according to their equals() methods. It must be exactly the same object pointed to.
Here is a simple example:
#Test
public void assertSame_assertNoSame_example() {
assertSame(employeeService.getEmployeeFromId(1), employeeService.getEmployeeFromId(1));
assertNotSame(employee, employeeService.getEmployeeFromId(1)); // We will get null as response
}
I have a test class like so:
public class CompareObjects {
public static class Obj {
public int i;
public Obj(int i) {
this.i = i;
}
}
public static void main(String[] args) {
Obj o1 = new Obj(0);
Obj o2 = new Obj(0);
if(o1 == o2) {
System.out.println("Equal");
}else{
System.out.println("Not equal");
}
}
}
I though the test would return "Equal", but it didn't. Why doesn't Java consider two objects with equal components not the same? Am I doing something wrong here? I have a feeling I completely overlooked something when I started learning Java.
Also, I tested the two against each other with the equals() method, and I get the same result. My reason for this question is that I would like to be able to test an ArrayList with the contains() method to see if one object has the same components as another and therefore equal. Any ideas?
== compares the references to the object. For example:
Obj a = new Obj(0);
Obj b = a;
//a == b
Try implementing equals():
public static class Obj {
public int i;
public Obj(int i) {
this.i = i;
}
#Override
public boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof Obj) || other == null) return false;
return i == ((Obj)other).i;
}
#Override
public int hashCode() {
return i;
}
}
Then, you can use if(o1.equals(o2)) {. However, this is not really a good example, read this (link) for more information.
== returns true only if you are comparing the same object [i.e. the same memory location].
If you want to compare objects by their fields, you have to overload the equals() method, in order to induce an equivalence relation over them.
public boolean equals(Object other){
return this.i == other.i;
}
Be sure that the equals() method respects reflexivity, symmmetry, transitivity.
== compares the reference equality, i.e if they refer to the same object in the memory.
You need to override equals() method, and use it whenever you want to compare their values. Also, override hashCode() which is used by HashMap for example.
The == operator does not check for equality in class data; rather, it checks to see if they are the same location in memory. If you did o2 = o1 instead of initializing them the same way, they would be the same location in memory, so o2==o1 would return true. However, since they were initialized some separately, it returns false. Instead, you should define an equals method and implement that.
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)
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.
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();
}
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)
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.
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