0

I'm overriding the equals(Object o) method of an Object that is identified by an string:

class User {
@Override
public boolean equals(Object o) {       
    return o != null && o.hashCode() == this.hashCode();
}

@Override
public int hashCode() {
    return id.hashCode();
}
}

But I'd like to check also if o is a subclass of this or vice versa before returning true in the method equals()

for the first case I can use if (o instance of User) but how can I make the check in the other way?

Thanks

Edit: Since I've not explained it correctly I'm going to explain the complete problem:

I have the class

public abstract class UniqueIdentifiedObject<E> {
    private E id;

    protected UniqueIdentifiedObject(E id) {
        super();
        this.id = id;
    }

    public E getId() {
        return id;
    }

    @Override
    public boolean equals(Object o) {
        return o != null && o.hashCode() == this.hashCode();
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }

}

and the idea is to inherit this class with an object when it is unique identified by a element: For example if the Users of my app are identified by a integer i'll use:

class User extends UniqueIdentifiedObject<Integer>

and for the Movies

class Movie extends UniqueIdentifiedObject<Integer>

The problem with this implementation of UniqueIdentifiedObject is that if call equals() with the movie with id = 1 and the user with the id=1 it will return true.

How can I solve this?

Addev
  • 31,819
  • 51
  • 183
  • 302
  • Are you asking this because `this` might be an instance of a subclass of `User` that did not override `equals`? – John B Oct 16 '12 at 10:34
  • 1
    Maybe this is what you are looking for : http://stackoverflow.com/a/2415417/914220 – Iulia Barbu Oct 16 '12 at 10:35
  • 1
    Downvote with no comment? Seems like a perfectly good question and I'm interested in the answers so +1 to restore the natural balance of the AndroidVerse. – Simon Oct 16 '12 at 10:35
  • @JoãoMendes When you say that `this` will never be a subclass of `o` that is not necessarily a safe assumption. If there are three class User, UserA and UserB where each inherits from the previous and only User overrides `equals`, then `this` could be a `UserB` and `o` could be a `UserA`. – John B Oct 16 '12 at 10:50
  • @JohnB Hmmmtrue. In which case, the accepted answer will fail. Interesting. I shall have to think upon this. – João Mendes Oct 16 '12 at 10:51
  • FYI, you should NEVER use `hashCode` to determine equality. By definition two objects may have the same hash code but not be equal whereas two equal object must have the same hash code. Your code could give a false positive. – John B Oct 16 '12 at 10:59

2 Answers2

4
this.getClass().isAssignableFrom(o.getClass());

Class.isAssignableFrom

From the javadoc:

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.

So the above checks that the class returned by this is a superclass of the class returned be o.

John B
  • 32,493
  • 6
  • 77
  • 98
  • The complete answer would have to be: `(this.getClass().isAssignableFrom(o.getClass()) || o.getClass().isAssignableFrom(this.getClass()))`. Otherwise, some edge cases will give incorrect results. – João Mendes Oct 16 '12 at 10:53
  • @JoãoMendes I didn't try to solve the problem (the code has a could issues I think - specifically using `hashCode` to determine equality) but answered the question about how to test that `o` is a subclass of `this` – John B Oct 16 '12 at 10:58
0

First: your code will work in most of the cases, but it is good practice to calculate equals() based on equalness, to avoid false-positives.

you can check dynamic types with "Class.isAssignableFrom", so e.g.

   this.getClass().isAssignableFrom(other.getClass())

will tell you, whether other is either the same class, or any subclas of "this". (As this must be an superclass to other)

I don't see the need to do that here, though

you can assure "this" to be a subclass of User, and if you can assure that other is of the same type, it should work out of the box.

so in your case, the method could look like

class User {
@Override
public boolean equals(Object o) {
   if (o==null) {
      return false;
   }
   if (o instanceof User) {
     return (o.id==null && id==null ) || (o.id.equals(id));
   }
}
@Override
public int hashCode() {
    return id.hashCode();
}
}
DThought
  • 1,340
  • 7
  • 18