Any possible to make two instantiations be equal in java? - java

I need to achieve this result:
public class question{
public static void main(String[]arg){
A a1=new A();
A a2=new A(2);
assert a2.equals(a1);
}
}
So I have tried:
class A{
A(){
return;
}
A(int x){
return;
}
}
public class d22 {
public static void main(String[]arg){
A a1=new A();
A a2=new A(2);
assert a2.equals(a1);
}
}
But obviously it's not working, is there any way to achieve the code upper? Thx.

There's nothing particularly magical about equals - it's a plain jane method defined in java.lang.Object.
You can override it.
This weird idea would work:
class A {
#Override public boolean equals(Object other) {
return other instanceof A;
}
}
would mean any A is equal to any other.

actually,the java object which is created by the key word new is allocated in the heap.So the result is false if you want compare a1 with a2,because the default equals method is to compare the object memory address.If you want compare two object ,you should rewrite the equals method to achieve your goal.

All classes in Java extends default Object class which contains method's equals() and toString(). Equals() method is used to compare instance of that particular class against another variable. You can override this method to define how equals should behave.
class A {
#Override
public boolean equals(Object other) {
if (!other instance of A) return false; // other is not same type as this class
if (other == this) return true; // both variables point to same object
return true; // you can compare other class attributes here
}
}
By default equals will return true if you are comparing two variables that point to same object. That means in your case that you obtain false when calling equals since your two variables point to different object created by new operator and you have not overriden equals() method to get different behavior than default one.

Related

java polymorphism aliasing issue

If there's 3 classes. A, B and C. class B extends A and class C extends B.
class A has equals method:
public boolean equals(A other)
{...}
class B has equals method:
public boolean equals(B other)
{...}
and class C has euals method:
public boolean equals(Object other)
{...}
And the main has these code lines:
A a = new A();
C c = new C();
a=c;
System.out.println(a.equals(c));
I can't understand why the equals method of class A is being executed.
I know that overloaded methods are bonded using static binding. But a points to the "C part of the object" after aliasing and there's the method equals of class C. Why isn't it the equals method of class C that will execute?
A method in a subclass overrides a method in the superclass only if the parameters have the same types.
The Object class defines an equals() method:
class Object {
public boolean equals(Object obj) {...}
}
When you define class A, it inherits the equals routine from Object. You define a new equals, but the parameter type is different, so it doesn't override the one in Object; instead, it becomes an overload. The result is that A has two overloaded equals methods:
class A {
public boolean equals(Object obj) {...} // inherited
public boolean equals(A other) {...} // the one you wrote
}
Similarly, the equals in B won't override either equals, so the result is three overloaded equals methods:
class B {
public boolean equals(Object obj) {...} // inherited from Object
public boolean equals(A other) {...} // inherited from A
public boolean equals(B other) {...} // doesn't override anything
}
In class C, the new equals method does override the one in Object, so there are still three equals methods:
class C {
public boolean equals(Object other) {...} // overrides the one in Object
public boolean equals(A other) {...} // inherited from A
public boolean equals(B other) {...} // inherited from B
}
Now, here's your code:
A a = new A();
C c = new C();
a=c;
System.out.println(a.equals(c));
When you say a.equals(c), the compiler sees that a has type A. Therefore it looks at the methods in A to see which one to execute. (The compiler doesn't know that a will have type C at run time; therefore, it won't look at the methods in C.)
There are two methods to choose from, as shown above:
public boolean equals(Object obj) {...} // inherited
public boolean equals(A other) {...} // the one you wrote
Both of them could be used on the parameter c, since c is an Object and it is an A. In that case, when one parameter is a subclass of the other, the compiler chooses the "closest" one, in essence. C is only two subclasses away from A, and it's three subclasses away from Object, so it chooses the overload with parameter A, which is the one you defined in A. And note that this equals method was never overridden. So it executes the code that you wrote in class A.
But suppose you had written:
System.out.println(a.equals((Object)c));
By casting c to an Object, you're forcing the compiler to look at it as an Object. Now when it chooses between the overloads, it must choose the one with the Object parameter, because an Object cannot automatically be converted to an A (because not every Object is an A). Thus, it would choose the inherited method. And since, at run time, the object actually is of class C, and since class C has an equals method that overrides the one in Object, in this case it would execute the code written in class C.
Your code is a nice example for demonstrating how overloading and overriding work. In real life, however, it's a bad idea to write an equals() method whose parameter is anything other than Object, because it won't override and it could lead to confusion. Also, it's a good practice to put #Override on any method that you think will override a method in a superclass. That way, if you goof and use the wrong parameters, the compiler will catch it before you get a run-time bug that could be very difficult to track down.
Short answer
Your method in child class gets overridden only when it have same method signature as that of parent class. Otherwise it doesn't.
Consider these two examples
Example 1
class A {
public boolean equals(A Other) {
System.out.println("A's method");
return true;
}
}
class C extends A {
public boolean equals(Object Other) {
System.out.println("C's method");
return true;
}
}
public class Driver {
public static void main(String[] args) {
A a = new C();
a.equals(null);
}
}
Output 1
A's method
Example 2
class A {
public boolean equals(A Other) {
System.out.println("A's method");
return true;
}
}
class C extends A {
public boolean equals(A Other) {
System.out.println("C's method");
return true;
}
}
public class Driver {
public static void main(String[] args) {
A a = new C();
a.equals(null);
}
}
Output 2
C's method
In example #1, you have changed the method signature when equals() method is defined in child class and so it doesn't qualify for method overriding. And so when calling this method from Driver class, parent's gets called.
whereas in example #2, the method signature in both parent and child are exactly the same and so method overriding takes place here and thus you get output that you were expecting in your question.
In Simple words, java handles aliasing during runtime. as overloaded method use static binding(compile time), it is calling A's equals method.
if you override equals method in class A.
#Override
public boolean equals(Object o){ ...}
it will be overridden method which uses dynamic binding(runtime) and C's equals method will be called.

Java overriding parent equals method

I have two classes Person and Teacher. In the Person class I check if the two objects passed in are equal using the compareTo method. In the Teacher class, the problem I'm working on states that I need to override the equals method in Person. In this equals method, the only way it would return true is if it's equal in both the equals method in Person and Teacher. My question is, when I check in the Teacher's equals method, do I just call super.equals(other) in order to check if the two objects are equal by the parent class or is there something else I need to do?
Person:
public class Person implements Comparable<Person> {
public boolean equals(Object other) {
try {
return this.compareTo(other) == 0;
}catch(Exception e) {
return false;
}
}
}
Teacher
public class Teacher extends Person {
private String facultyID;
#Override
public boolean equals(Object other) {
boolean personEquals = super.equals(other);
try {
Teacher teach1 = (Teacher)other;
boolean idEquals = this.facultyID.equals(teach1.facultyID);
if(idEquals && personEquals)
return true;
return false;
}catch(Exception e) {
return false;
}
}
}
Basically, the contract of Object#equals states:
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true
And the implementation of Teacher#equals doesn't meet this requirement. For cases when implementing equals method in a class that inherits from another that is not Object e.g. Teacher, you should verify if the type of the object to be compared is the same as the class you're comparing. To achieve this, you should use getClass().equals:
public class Teacher extends Person {
private String facultyID;
#Override
public boolean equals(Object other) {
//this line is nonsense, not all Persons are Teachers
//boolean personEquals = super.equals(other);
//avoid using try-catch
//try {
//verify that the other object is not null
if (other == null) {
return false;
}
//verify that the other object is specifically a Teacher, not a super or a subclass of it
if (this.getClass().equals(other.getClass()) {
//here comes the real check
Teacher otherTeacher = (Teacher)other;
return this.facultyID.equals(otherTeacher.facultyID);
}
return false;
}
}
Do similar for Person in case it should not allow comparing against subclasses of it.

How to turn this into an override?

How do you make something into an override? My book offers a basic explanation but does not show how to implement it into your code and the internet is just as helpful. My directions say to...
Create a Java class called Rational:
...
that overrides equals such that if the parameter’s numerator and denominator are exactly equal to the current objects numerator and denominator the method returns true, and false otherwise.
I thought I had figured out how to do the override method but was upon further investigation it looks like I messed it up.
Rational.Equals(Rational x){
if(x.numerator == a && x.denominator == b)
{
return true;
}
else
{
return false;
}
}
Any tips or good reading on how to make this into an override method?
Briefly, a method overrides another when a subclass provides its own implementation of a method with the same signature (return type, name and parameter types) as a super class, eg:
class SuperClass {
void someMethod() {
// some impl
}
}
class SubClass extends SuperClass {
#Override // #Override annotation not necessary, but good practice
void someMethod() {
// some overriding impl
}
}
Classes have methods, and when a class extends another class (every single class extends Object class) it can declare a method with the same signature as the one in the superclass, so it is called an override. I think you are expected to write something like:
class Rational {
int numerator, denominator;
#Override
public boolean equals(Object o) {
if (o instanceof Rational) {
Rational rational = (Rational) o;
return numerator == rational.numerator && denominator == rational.numerator;
}
return false;
}
}

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 - abstract class, equals(), and two subclasses

I have an abstract class named Xpto and two subclasses that extend it named Person and Car. I have also a class named Test with main() and a method foo() that verifies if two persons or cars (or any object of a class that extends Xpto) are equals. Thus, I redefined equals() in both Person and Car classes. Two persons are equal when they have the same name and two cars are equal when they have the same registration.
However, when I call foo() in the Test class I always get "false". I understand why: the equals() is not redefined in Xpto abstract class. So... how can I compare two persons or cars (or any object of a class that extends Xpto) in that foo() method?
In summary, this is the code I have:
public abstract class Xpto {
}
public class Person extends Xpto{
protected String name;
public Person(String name){
this.name = name;
}
public boolean equals(Person p){
System.out.println("Person equals()?");
return this.name.compareTo(p.name) == 0 ? true : false;
}
}
public class Car extends Xpto{
protected String registration;
public Car(String registration){
this.registration = registration;
}
public boolean equals(Car car){
System.out.println("Car equals()?");
return this.registration.compareTo(car.registration) == 0 ? true : false;
}
}
public class Teste {
public static void foo(Xpto xpto1, Xpto xpto2){
if(xpto1.equals(xpto2))
System.out.println("xpto1.equals(xpto2) -> true");
else
System.out.println("xpto1.equals(xpto2) -> false");
}
public static void main(String argv[]){
Car c1 = new Car("ABC");
Car c2 = new Car("DEF");
Person p1 = new Person("Manel");
Person p2 = new Person("Manel");
foo(p1,p2);
}
}
As the others say, the signature of the method you override must be exactly the same. When overriding methods, to make sure you are overriding, use the #Override annotation above the function, so IDEs like Eclipse will warn you if you changed the method.
This is what it would look like:
#Override
public boolean equals(Object obj){
...Your code here...
}
I would suggest to override hashCode() as well because when inserting items into lists, sets, hastables, etc... for equality (and performande) hashCode() is used (and sometimes equals() is not!)
So your final code would be:
#Override
public boolean equals(Object obj){
...Your code here...
}
#Override
public int hashCode(){
...Your code here...
}
More info at the javadoc
I understand why: the equals() is not
redefined in Xpto abstract class.
Actually equals() isn't redefined anywhere in your code. To override it, your method has to have Object as parameter type and you have to cast it (after testing with instanceof to return false when instances of two different subclasses are compared).
declaring public boolean equals(Person p) or public boolean equals(Car p) does not override Object's public boolean equals(Object o), it's just a new method that is never called.
Here's how I would go about it:
public abstract class Xpto {
}
public class Person extends Xpto{
protected String name;
public Person(String name){
this.name = name;
}
public boolean equals(Object o){
if(o == null || !getClass().equals(o.getClass())
return false;
Person p = (Person) o;
System.out.println("Person equals()?");
return this.name.compareTo(p.name) == 0 ? true : false;
}
}
public class Car extends Xpto {
protected String registration;
public Car(String registration){
this.registration = registration;
}
public boolean equals(Object o){
if(o == null || !getClass().equals(o.getClass())
return false;
Car car = (Car) o;
System.out.println("Car equals()?");
return this.registration.compareTo(car.registration) == 0 ? true : false;
}
}
public class Teste {
public static void foo(Xpto xpto1, Xpto xpto2){
if(xpto1.equals(xpto2))
System.out.println("xpto1.equals(xpto2) -> true");
else
System.out.println("xpto1.equals(xpto2) -> false");
}
public static void main(String argv[]){
Car c1 = new Car("ABC");
Car c2 = new Car("DEF");
Person p1 = new Person("Manel");
Person p2 = new Person("Manel");
foo(p1,p2);
}
}
Every class inherit an equals(Object) method from the Object class. Thus, Xpto does not need to define such a method.
When one overrides this method in subclasses (namely: Person, Car) one must define it with the exact same signature. In other words, the parameter of the equals method must be of type Object, and the method implementation must downcast it.
The Javadoc states that you need to override the equals method with object as a parameter.
Indicates whether some other object is
"equal to" this one.
Therefore your subclasses equals methods should look something like this:
public class Car extends Xpto
{
protected String registration;
public Car(String registration)
{
this.registration = registration;
}
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (obj == this)
{
return true;
}
if (!obj.getClass().isAssignableFrom(getClass()))
{
return false;
}
Car car = (Car) obj;
return this.registration.compareTo(car.registration) == 0 ? true : false;
}
}
It is generally very difficult/impossible to fully fulfill the equals contract and still have two different classes in the hierarchy equal to each other, and it is generally not done. Generally an equals method tests for the class being the same (so two instances of the same subclass will equal each other, but two instances of two different subclasses will not).
However, in your case it is possible to implement an equals in Xpto since there is only one property. The obvious way to do this is to define an abstract method in Xpto, and then override equals in Xpto as well:
public class Xpto {
protected abstract String getIdentity();
#Override
public boolean equals(Object o) {
if (o == null) return false;
//Typical implementation
//if (getClass() != o.getClass()) return false;
if (!(o instanceof Xpto)) return false; //risky implementation, but will allow a car to compare to a person
return getIdentity().equals((Xpto) o.getIdentity());
}
#Override
public int hashCode() {
return getIdentity().hashCode();
}
}
Others have pointed out that you did not actually override equals in your implementation. In the future you can get the compiler to help you out with that by using the #Override annotation. In your case you would have gotten a compile error early which would have saved you some time.
Your equals method should look like:
#Override public boolean equals(Object o) {
if (!(o instanceof YourType)) {
return false;
}
YourType yt = (YourType)o;
... // rest here
}
Also, don't forget to override hashCode as well, to be able to properly use your types in collections.
You are not overriding the equals() method, instead you overload it. Change the signature to
public boolean equals(Object o)
And then cast o to Person/Car and do the comparison.
And BTW, you could compare the strings with equals() as well:
return registration.equals(car.registration);
Your subclasses are defining equals(Person) or equals(Car), neither of which is going to like being passed an Xpto. If you declare them both as equals(Xpto), or better yet equals(Object) so that they'll work in collections, then your problem should go away.
Note, if you redeclare the equals() methods this way, (1) you'll need to check the classes of the objects you get passed, since you can't guarantee they're Cars or Persons anymore, and (2) you'll probably want to override getHashCode() as well, especially if you decide to make them both equals(Object), cause getHashCode() should return equal hash codes for two objects that are equal.

Categories