what is 'this' referes to in overriding equals method in java - java

Public Class ClassATest {
public static void main(String a[]) {
ClassA a = new ClassA(10);
ClassA b = new ClassA(10);
if(a.equals(b)) {
//do something.
}
}
}
Public ClassA {
private int someValue;
ClassA(int val) {
someValue = vall
}
// Overriding equals method as..
public boolean equals(object o) {
if((o instance of Object) && (((ClassA)o).getSomeMethod() == **this**.someValue) {
return true;
}
}
Question is.. What is this referring to?
Assuming implementation a.equals(b) as -- b instance of Object && b.getSomeMethod == this.someValue;
Can you please explain.. whis 'this' refer to here ? this.someValue means what??
/

It means the instance of the class that the code is in, in your example it would be an instance of the class ClassA

Related

Why containValue method of HashMap class is returning False for the below program?

Here I am trying to override both equals method as well as hash code method. But containsValue() method throwing False. Even the hashcode overridden class is getting called but i think equals method is not getting properly called. please help me with this.
import java.util.*;
class Test{
int i;
Test(int i)
{
this.i=i;
}
public boolean equals(Test t)
{
if(this.i==t.i){
return true;
}
else{
return false;
}
}
public int hashCode() { //Overriding hashCode class
int result = 17;
result = 37*result + Integer.toString(i).hashCode();
result = 37*result;
return result;
}
}
class TestCollection13{
public static void main(String args[]){
HashMap<Integer,Test> hm=new HashMap<Integer,Test>();
hm.put(1,new Test(1));
hm.put(2,new Test(2));
hm.put(3,new Test(1));
hm.put(4,new Test(4));
for(Map.Entry m:hm.entrySet()){
Test t2=(Test)m.getValue();
System.out.println(m.getKey()+" "+t2.hashCode());
}
System.out.println(hm.containsValue(new Test(2)));
}
}
Your method public boolean equals(Test t) does not override Object.equals(Object). You need to update your method signature and check the class type:
#Override
public boolean equals(Object o) {
return o instanceof Test
&& ((Test)o).i == this.i;
}
equals should be defined to take an Object, not a Test:
#Override
public boolean equals(Object other)
You could easily detect this by explicitly annotating the method with #Override in which case the compiler would detect this bug.
Method equals() takes Object as a parameter, so in your code you are not overriding equals() method but overloading it. So you need to change the incoming parameter to Object. Your method should be something like this:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Test)) return false;
Test test = (Test) o;
return this.i == test.i;
}
Also I would add getter and setter for your i member.

Why does Set allow a duplicate here?

I have the code below:
class Animal {
int i;
public Animal(){
i=13;
}
public String toString(){
return "Animal "+i;
}
}
//
public class NewMain {
public static void main(String[] args) {
HashSet hs=new HashSet();
boolean b=hs.add(new Animal());
boolean b1=hs.add(new Animal());
System.out.println(b+" "+b1);
for(Object o:hs)
{
System.out.println(hs);
}
}
}
I know that Set does not allow duplicates, but why does the above code seem to allow two identical values?
Because Java has no way of knowing that your two instances are the same.
You need to override equals() and hashcode()
.
As has already been pointed out, you need to override hashCode and equals. You can compare on the int i with something like,
class Animal {
int i;
public Animal() {
i = 13;
}
#Override
public String toString() {
return "Animal " + i;
}
#Override
public int hashCode() {
return Integer.hashCode(i);
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Animal) {
return ((Animal) obj).i == i;
}
return false;
}
}
Then I would suggest you use generics with your Collection. Also, you should print the instance (not the Collection) in your loop. Something like,
public static void main(String[] args) {
Set<Animal> hs = new HashSet<>();
boolean b = hs.add(new Animal());
boolean b1 = hs.add(new Animal());
System.out.println(b + " " + b1);
for (Animal a : hs) {
System.out.println(a);
}
}
And I get (the expected)
true false
Animal 13
You haven't overridden hashcode and equals in the Animal class. Therefore, these methods are inherited from java.lang.Object.
The inherited behaviour (from Object) is that objects are only equal if they are the same object.
In this case, a suitable pair of overrides for equals and hashcode would be something like this:
#Override
public boolean equals(Object other) {
return other instanceof Animal &&
other != null &&
((Animal) other).i == this.i;
}
#Override
public int hashCode() {
return i;
}
(Note that if you start creating subclasses of Animal, you need to think carefully on how best to implement equals(Object). By code above doesn't attempt to deal with that ...)

equals method override issue

I am a new learner of java. I have overridden equals and hashcode for my Animal class. I would expect that, using a HashSet<Animal> as below, only one Animal will be inserted into the HashSet. However the second Animal object is getting added to the set despite having the same properties. Can anyone look into it?
import java.util.*;
class SetTest
{
public static void main(String [] args)
{
Set<Animal>s=new HashSet<Animal>();
Animal a=new Animal(2);
boolean b1=s.add(a);
System.out.println("hi "+b1);
Animal b=new Animal(2);
boolean b2=s.add(b);
System.out.println("hi "+b2);
}
}
class Animal
{
int t;
Animal(int a)
{
t=a;
}
public boolean equals(Object O)
{
if(O instanceof Animal && ((Animal)O).t==t)
return true;
return false;
}
public int hashcode()
{
return t;
}
}
Output:
hi true
hi true
Thanks a Lot.
You didn't override hashCode(). You introduced another method called hashcode(). Case matters.
When your intention is to override a method, always use the #Override annotation:
#Override
public int hashcode()
If you had done that, the compiler would have noticed the typo and have refused to compile the class.
Your code has a mistype hashcode: write hashCode not hashcode .
import java.util.*;
class SetTest {
public static void main(String [] args) {
Set<Animal>s=new HashSet<Animal>();
Animal a=new Animal(2);
boolean b1=s.add(a);
System.out.println("hi "+b1);
Animal b=new Animal(2);
boolean b2=s.add(b);
System.out.println("hi "+b2);
}
}
class Animal {
int t;
public Animal(int a) {
t=a;
}
#Override
public boolean equals(Object O) {
return O instanceof Animal
&& ((Animal)O).t==t;
}
#Override
public int hashCode() {
return t;
}
}
If you are using eclipse, you can make use of the source code generator and there by avoiding the common human error(the like you did it over here. Right click on the class -> source -> generate hashcode and equals methods. which will pop up window. There you can choose the fields which you need to consider for equals(equality of object) and hashcode generation.
Java uses hashCode and equals method to check if two objects are equal. HashSet internally uses HashMap. You can refer HashMap.put(K key, V value) method for more details.

Regarding overriding equals method in java

I tried to override equals and hashcode methods in a class. It is a subclass of another class which does not implement the equals method and hashCode methods.
Eclipse gave the below warning .
The super class ABC does not implement equals() and hashCode() methods.
The resulting code may not work correctly.
Why is the above warning given ? Under what circumstances it may not work correctly ?
If you say a.equals(b) versus b.equals(a) it is reasonable to expect the behaviour to be the same. But if they are of corresponding types B and A related by inheritance and only one of them properly implements equals then the behaviour will be different in those two examples.
Here, A is the superclass and does not implement equals at all (so it inherits java.lang.Object.equals). Subclass B overrides equals to depend on the name field.
class A {
String name;
public A() {
this.name = "Fred";
}
}
class B extends A {
public boolean equals(Object o) {
A a = (A)o;
return a != null && a.name.equals(this.name);
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
System.out.println(a.equals(b) == b.equals(a));
}
}
Unsurprisingly, the output is false, thus breaking symmetry.
Have you tried super class override the equals ... and then auto generate subclass override implementation...
I am sure it will be differnt. it will have call to super.equals()
in current auto generated implementation it is only checking values in child class..
Consider below scenario and you will understand why warning.
abstract Class A{
private int a;
public void setA(int a){
this.a=a;
}
}
Class B extends A{
private int x;
public void setX(int x){
this.x=x;
}
#Override
public boolean equals(Object obj) { // This does not call Super.equals
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
B other = (B) obj;
if (x != other.x)
return false;
return true;
}
}
and in main Method try
B b1= new B();
b1.setA(10);
b1.setX(20);
B b2= new B();
b2.setA(20);
b2.setX(20);
if(b1.equals(b2)){
System.out.println("Warning was Right");
}

java class, extending external API functionality

I have an external API (I can't modify it) with class "A" and local class "B" which overrides methods of "A" and adds an additional function.
I need to use one of them according to some parameter "is_A".
/------ API (A.java) -----/
package A;
public class A {
public int pingA( int value ) {
return value;
}
}
/------ my class (B.java) -----/
package B;
import A.*;
public class B extends A {
#Override
public int pingA( int value ) {
return value;
}
public int pingB( int value ) {
return value;
}
public static void main(String[] args) {
final boolean is_A = false;
A obj;
if (is_A) {
obj = new A();
} else {
obj = new B();
}
if (!is_A) {
int n = obj.pingB(3);
}
}
}
In this case I want to use class "B", but the command "int n = obj.pingB(3);" is not compiled because there is no method pingB in A.
The exact message is:
cannot find symbol
symbol: method pingB(int)
location: class A.A
You're adding a new method in a subclass which does not exist in the super class. There is no way to call the new method in the subclass using a reference to the superclass. You'd have to cast to to the subclass type to use the new method.
You could do something like:
A obj = new B();
if (obj instance of B) {
B b = (B)obj;
int n = b.pingB(3);
}
Here B is a A but A is not a B so it doesn't have the pingB(int) method.
You need to cast obj back to B.
if (!is_A) {
int n = ((B) obj).pingB(3);
}
You can by the way better use the instanceof keyword instead of is_A.
if (obj instanceof B) {
int n = ((B) obj).pingB(3);
}
You need to cast to your derived class to be able to call it's methods. Usually that is done with and if( obj instanceof B ) but as you already have a boolean with that information it's going to look like this:
public static void main(String[] args) {
final boolean is_A = false;
A obj;
if (is_A) {
obj = new A();
} else {
obj = new B();
}
if (!is_A) {
int n = ((B) obj).pingB(3);
}
}
obj is still having the type A (-> you declared A obj;) -> this way the type binding does not work for compilation.

Categories