Reputation:
I am comparing same objects using == and equals() method but both of them are failing. I tried four combinations as follows. Please someone guide where I am making mistake.
public class Question {
int rollNo;
String name;
Question(int rollNo, String name) {
this.rollNo = new Integer(rollNo);
this.name = new String(name);
}
public int getRollNo() {
return new Integer(rollNo);
}
public void setRollNo(int rollNo) {
if(rollNo>0) this.rollNo = rollNo;
}
public String getName() {
return new String(name);
}
public void setName(String name) {
if(name!=null) this.name = name;
}
public static void main(String[] args) {
Question obj1 = new Question(123, "Student1");
Question obj2 = new Question(123, "Student1");
Question obj3 = new Question(456, "Student2");
// All if conditions are evaluating to false
if(obj1 == obj2) System.out.println("Equal objects 1 and 2 using ==");
if(obj1.equals(obj2)) System.out.println("Equal objects 1 and 2 using equals()");
if(obj1 == new Question(123, "Student1")) System.out.println("Equal objects 1 and 2 using == and new");
if((new Question(123, "Student1")).equals(obj2)) System.out.println("Equal objects 1 and 2 using equals() and new");
}
}
I welcome suggestions on my code quality too as I have just started coding.
Upvotes: 0
Views: 1022
Reputation: 719659
It fails with ==
because the Question
objects are different objects. (The ==
operator for reference types tests to see if the references are for the same object.)
It fails with equals
because you are using the Object::equals(Object)
method. That method is specified to have the same meaning as ==
.
If you want Question::equals(Object)
to behave differently, you need to override the method inherited from Object
by adding a method like this:
@Override
public boolean equals(Object other) {
// implement this according to the spec to give the equality
// semantics you need
}
An actual implementation might look like this:
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Question) {
Question other = (Question) obj;
return this.rollNo == other.rollNo &&
this.name.equals(other.name);
} else {
return false;
}
}
I noticed some other problems in your code. For example:
Question(int rollNo, String name) {
this.rollNo = new Integer(rollNo);
this.name = new String(name);
}
public
.this.rollNo
is declared as an int
, creating an Integer
and assigning that is pointless ... and inefficient. What will happen is the Integer
will be unboxed to get its value, and the object will then be thrown away. Just assign rollNo
to this.rollNo
.Integer
instance explicitly, the correct way to do it is to use Integer.valueOf(int)
. That makes uses of a built-in cache of Integer
objects.new String(name)
is unnecessary and inefficient. Strings are immutable. There is not need to copy them. Certainly, not here.Upvotes: 2
Reputation: 5118
A class is a reference type, so when checking equality, it will be false any time you're not comparing two references to the same object. All the values in the objects may be the same, but they are not the same object.
If you want to be able to compare two instances of your Question
class like this, you'll need to override equals
and getHashCode
. See here: https://www.geeksforgeeks.org/overriding-equals-method-in-java/
Upvotes: 1