Casting an object in equals Java 5

Discussion in 'Java' started by crazzybugger, Sep 30, 2008.

  1. crazzybugger

    crazzybugger Guest

    Hi,
    I am stuck with a compiler warning while trying to cast an
    object inside equals method.
    Consider class A<I>{ }
    inside this class, I am trying to override equals method. However, I
    am not able to cast the received object into the proper type without
    compiler warning.

    Consider this implementation of equals
    public boolean equals(Object that){
    if(that instanceof A){
    A<I> that1 = this.getClass().cast(that); // here I am
    getting compiler warning.
    // perform comparisons...
    }
    }

    what is the right way to cast here ?
    thank you...
    crazzybugger, Sep 30, 2008
    #1
    1. Advertising

  2. crazzybugger

    crazzybugger Guest

    On Sep 30, 1:25 pm, Sabine Dinis Blochberger <>
    wrote:
    > crazzybugger wrote:
    > > Hi,
    > >       I am stuck with a compiler warning while trying to cast an
    > > object inside equals method.
    > > Consider class A<I>{ }
    > > inside this class, I am trying to override equals method. However, I
    > > am not able to cast the received object into the proper type without
    > > compiler warning.

    >
    > > Consider this implementation of equals
    > > public boolean equals(Object that){
    > >      if(that instanceof A){
    > >          A<I> that1 = this.getClass().cast(that);   // here I am
    > > getting compiler warning.
    > >         // perform comparisons...
    > >     }
    > > }

    >
    > > what is the right way to cast here ?
    > > thank you...

    >
    > Since you already test if "that" is an instance of "A", do you even need
    > to cast it (assuming "A" is the class that implements this "equals()")?
    >
    > A cast only tells the compiler to pretend/handle it as if that this
    > object is of type X, it does not convert the object in any way.
    >
    > <http://mindprod.com/jgloss/cast.html>


    If I donot cast it as an object of A<I> how can I access the methods &
    attributes of A ? Besides If I try casting it as object of type 'A'
    and not as A<I>, I get the 'not parameterised' warning!!!
    crazzybugger, Sep 30, 2008
    #2
    1. Advertising

  3. crazzybugger <> wrote:
    > Consider class A<I>{ }
    > public boolean equals(Object that){
    > if(that instanceof A){
    > A<I> that1 = this.getClass().cast(that); // here I am getting compiler warning.


    Casting from Object to a parameterized type is fragile, because
    not even at runtime can it be verified that the complete type
    is correct. You can always cast to "A": A that1 = (A)that;
    Sometimes that may be enough to determine equality.

    If you look at how Sun did it, e.g. in AbstractMap<K,V>, then
    you'll see that they simply did it analogously to

    A<I> that1 = (A<I>) that;

    and either ignored or suppressed the resulting warning.

    PS: I think, that "normal" programs should never have a need
    for .getClass(). (Application servers are not "normal" and
    neither are class viewers in this context :)
    Andreas Leitgeb, Sep 30, 2008
    #3
  4. crazzybugger wrote:
    > On Sep 30, 1:25 pm, Sabine Dinis Blochberger <>
    > wrote:
    >> crazzybugger wrote:
    >>> Hi,
    >>> I am stuck with a compiler warning while trying to cast an
    >>> object inside equals method.
    >>> Consider class A<I>{ }
    >>> inside this class, I am trying to override equals method. However, I
    >>> am not able to cast the received object into the proper type without
    >>> compiler warning.
    >>> Consider this implementation of equals
    >>> public boolean equals(Object that){
    >>> if(that instanceof A){
    >>> A<I> that1 = this.getClass().cast(that); // here I am
    >>> getting compiler warning.
    >>> // perform comparisons...
    >>> }
    >>> }
    >>> what is the right way to cast here ?
    >>> thank you...

    >> Since you already test if "that" is an instance of "A", do you even need
    >> to cast it (assuming "A" is the class that implements this "equals()")?
    >>
    >> A cast only tells the compiler to pretend/handle it as if that this
    >> object is of type X, it does not convert the object in any way.
    >>
    >> <http://mindprod.com/jgloss/cast.html>

    >
    > If I donot cast it as an object of A<I> how can I access the methods &
    > attributes of A ?


    You can't. But I don't understand your "this.getClass().cast(that);"
    I'd try

    A<I> that1 = (A<I>) that;
    that1.methodOfA();


    By the way, your choice of example variable names confuses me. I'd maybe
    have chosen them like this ...

    public boolean equals(Object object) {
    if (object instanceof A) {
    A<I> a = (A<I>) object;
    ...


    > Besides If I try casting it as object of type 'A'
    > and not as A<I>, I get the 'not parameterised' warning!!!


    Which is as it should be, why would you expect anything else?


    --
    RGB
    RedGrittyBrick, Sep 30, 2008
    #4
  5. On 30-9-2008 9:40, crazzybugger wrote:
    > Hi,
    > I am stuck with a compiler warning while trying to cast an
    > object inside equals method.
    > Consider class A<I>{ }
    > inside this class, I am trying to override equals method. However, I
    > am not able to cast the received object into the proper type without
    > compiler warning.
    >
    > Consider this implementation of equals
    > public boolean equals(Object that){
    > if(that instanceof A){
    > A<I> that1 = this.getClass().cast(that); // here I am
    > getting compiler warning.
    > // perform comparisons...
    > }
    > }
    >
    > what is the right way to cast here ?
    > thank you...


    if (that instanceof A) {
    A<?> that1 = (A<?>)that;
    ...
    }

    The actual type parameter of "that" isn't known at runtime, so you can
    only cast it safely to an A of unknown type, i.e. A<?>.

    I wouldn't use getClass().cast() if A can have subclasses, let's say B
    and C, because this cast will fail if "this" is an instance of B and
    "that" is an instance of C.
    --
    Regards,

    Roland
    Roland de Ruiter, Sep 30, 2008
    #5
  6. Eric Sosman <> wrote:
    > Andreas Leitgeb wrote:
    >> PS: I think, that "normal" programs should never have a need
    >> for .getClass(). (Application servers are not "normal" and
    >> neither are class viewers in this context :)

    >
    > One of the few places where .getClass() seems essential is in
    > implementing .equals() for non-final classes:


    In my Java classes they told me not to do that at all.
    Either make these classes (or equals() itself, along with
    hashCode()) final or abstract.

    Btw., I think that class-equality is not a necessary
    condition for a contract-fulfilling (and non-trivial)
    equals(). It's quite feasible, that a subclass, while
    adding new fields and stuff, still adheres to the base-
    class' definition of equality. Proper implementation
    of this behaviour would have final equals() & hashCode()
    in the non-final baseclass.

    Apart from that case there is the situation that one should
    either avoid entirely, or solve with reflection (and getClass()
    is kind of an entry-point of reflection).

    Any examples of where such a class-hierarchy with non-leaf
    classes having to be non-abstract really and inevitably
    comes up? (I'd like to know. I don't deny the possibility)

    > class Super {
    > public boolean equals(Object obj) {
    > if (obj.getClass() != Super.class) return false;


    If it were really necessary, I'd probably rather do it
    as: if (obj.getClass() != getClass()) return false;
    to also deal with classes that do not override equals()
    but still want their instances to be able to equal other
    instances of the same subclass, or even themselves, based
    only on baseclass features.

    > Does anyone know of a smoother way to do this?

    Yes: avoid the situation :)

    Make all leaf-classes final, and all others abstract.
    OR: Allow subhierarchies where subclass instances can legally
    equal instances of any other class within that subhierarchy.
    Andreas Leitgeb, Oct 1, 2008
    #6
  7. Andreas Leitgeb <> wrote:
    > Eric Sosman <> wrote:
    >> class Super {
    >> public boolean equals(Object obj) {
    >> if (obj.getClass() != Super.class) return false;


    Another caveat with this approach:
    if some subclass's equals() calls super.equals(), it may
    get (unexpected) wrong negatives, even for identical
    objects...
    Andreas Leitgeb, Oct 1, 2008
    #7
  8. Andreas Leitgeb wrote:
    > Eric Sosman <> wrote:
    >> Andreas Leitgeb wrote:
    >>> PS: I think, that "normal" programs should never have a need
    >>> for .getClass(). (Application servers are not "normal" and
    >>> neither are class viewers in this context :)

    >> One of the few places where .getClass() seems essential is in
    >> implementing .equals() for non-final classes:

    >
    > In my Java classes they told me not to do that at all.
    > Either make these classes (or equals() itself, along with
    > hashCode()) final or abstract.

    ....

    I take a rather different position. If a non-final class overrides
    equals and hashCode, its documentation should include rules for subclass
    equality.

    Treating an object as being unequal from instances of its class's
    subclasses is one possible rule, but not the only one.

    For example, the List interface has a set of rules for equals and
    hashCode that allow equality comparison of any two instances of any
    class implementing List, regardless of whether the two objects are of
    the same class or not.

    AbstractList implements those rules using only the methods any List
    implementation must have.

    Patricia
    Patricia Shanahan, Oct 1, 2008
    #8
  9. Eric Sosman <> wrote:
    > Andreas Leitgeb wrote:
    >> In my Java classes they told me not to do that at all.
    >> Either make these classes (or equals() itself, along with
    >> hashCode()) final or abstract.


    > Maybe I've misunderstood, but this seems crazy.


    In that class we had our "hands-on" example, some class
    describing a (3D-)Point, and it had an equals() that compared
    all three coordinates, and a hashCode() that was consistent
    with equals().

    Then the instructor raised the point of deriving a "ColoredPoint"
    and showed us the bad effect of the naive approach for overriding
    equals (and hashCode()) in ColoredPoint.

    Generally (my own words):
    One can only weaken(**) the equality relation when deriving
    instanciable classes from other instanciable classes.
    Otherwise, it results in an asymmetric (thus broken)
    relation. (**): i.e.: grow the equivalence classes

    But in subhierarchies, one generally wants to make the
    subclasses equality more fine-grained. That's the problem.

    The solutions for this problem are these:

    - Document some appropriate contract for all subclasses

    - Only care about leaf-classes' equals(). Let non-leaf
    classes inherit Object's equals() or make them
    abstract.

    - Prevent subclassing (make the class final).

    - Just prevent subclasses from fiddling with .equals()
    or hashCode() (make these methods final)

    - Make the baseclass's .equals() artificially more finegrained,
    by growing only those equivalence classes that only
    contain direct baseclass-instances.
    This requires using getClass(), and the result is, that
    any subclass cannot tell it apart from Object.equals().

    While technically ok and legal, it (imho) contradicts
    OO-principles, just like having any other method that does
    something useful for instances of the class it's defined
    in, but does nothing for any subclass-instance. brrr.

    Those who use getClass() for equals() probably also torture
    baby dogs in their leisure time ;-)
    Andreas Leitgeb, Oct 1, 2008
    #9
  10. Lew <> wrote:
    > He [Bloch] does recommend to "Design and document for inheritance or
    > else prohibit it" (Item 17), which Andreas's instructors might have twisted.


    Don't attribute to my instructor's what you can attribute to me :)

    I was just omitting the omnipresent principle of that my class can
    have any cruel behaviour, that may require the user/subclasser to
    jump through hoops, as long as I document each and every such hoop.

    With that implicit alternative it's pretty well the same as how
    I understood Bloch.
    Andreas Leitgeb, Oct 1, 2008
    #10
  11. Patricia Shanahan <> wrote:
    > Andreas Leitgeb wrote:
    >> In my Java classes they told me not to do that at all.
    >> Either make these classes (or equals() itself, along with
    >> hashCode()) final or abstract.


    That was just part of the whole message. These three lines
    alone do not represent my nor (as I believe) my instructor's view.

    The other crucial part was the context referred to by "that".

    "That" (roughly): "designing a class and its .equals() such,
    that it requires getClass() for its implementation"

    > I take a rather different position. If a non-final class overrides
    > equals and hashCode, its documentation should include rules for subclass
    > equality.

    These rules, however may have to be quite restrictive then.

    > For example, the List interface has a set of rules for equals and
    > hashCode that allow equality comparison of any two instances of any
    > class implementing List, regardless of whether the two objects are of
    > the same class or not.


    The above mentioned rules probably disallow overriding .equals() to
    make it more restrictive - e.g. not let it depend on a new subclass-
    specific independent(on baseclass) attribute.

    In most other cases than collection classes, such rules would be de facto
    prohibitive (against overriding .equals() at all).
    Andreas Leitgeb, Oct 1, 2008
    #11
  12. crazzybugger

    Tom Anderson Guest

    On Wed, 1 Oct 2008, Andreas Leitgeb wrote:

    > Eric Sosman <> wrote:
    >> Andreas Leitgeb wrote:
    >>> In my Java classes they told me not to do that at all.
    >>> Either make these classes (or equals() itself, along with
    >>> hashCode()) final or abstract.

    >>
    >> Maybe I've misunderstood, but this seems crazy.

    >
    > In that class we had our "hands-on" example, some class
    > describing a (3D-)Point, and it had an equals() that compared
    > all three coordinates, and a hashCode() that was consistent
    > with equals().
    >
    > Then the instructor raised the point of deriving a "ColoredPoint"
    > and showed us the bad effect of the naive approach for overriding
    > equals (and hashCode()) in ColoredPoint.


    My take on this is that subclassing, and overriding equals, is okay, as
    long as the symmetry of equals is preserved. So, ColouredPoint can
    override equals and compare colour as well as position when it's comparing
    itself to another ColouredPoint, but when comparing itself to a normal
    Point, it should just compare coordinates, as a Point would. Like this:

    public boolean equals(Object that) {
    if (that instanceof Point) return equals((Point)that) ;
    else return false ;
    }

    public boolean equals(Point that) {
    if (that instanceof ColouredPoint) return equals((ColouredPoint)that) ;
    else return (this.x == that.x) && (this.y == that.y) ;
    }

    public boolean equals(ColouredPoint that) {
    return (this.x == that.x) && (this.y == that.y) && (this.colour.equals(that.colour)) ;
    }

    An equals method implemented like this is reflexive, and symmetric even in
    the presence of mixed types. What it isn't is transitive:

    Point p = new Point(5, 5) ;
    Point q = new ColouredPoint(5, 5, Color.RED) ;
    Point r = new ColouredPoint(5, 5, Color.BLUE) ;
    p.equals(q) ; // true
    p.equals(r) ; // true
    q.equals(r) ; // false!

    Which could be a problem. Or might not be. It's definitely not pretty, and
    feels like an accident waiting to happen.

    As for hashCode, if you want to to be consistent with equals, which is
    generally considered a must, then you can't override the version in Point,
    since the version of equals in Point is serving as the benchmark for
    equality. I doubt this will be a huge problem in practice.

    tom

    --
    We must perform a quirkafleeg
    Tom Anderson, Oct 1, 2008
    #12
  13. crazzybugger

    zerg Guest

    Andreas Leitgeb wrote:
    > Then the instructor raised the point of deriving a "ColoredPoint"
    > and showed us the bad effect of the naive approach for overriding
    > equals (and hashCode()) in ColoredPoint.


    This sort of situation should induce one to reassess the object
    relations in an OO design.

    In particular, ColoredPoint may not make much sense as a "kind of"
    point, so much as a combination of a point and a color. Which means
    instead of inheriting from Point (or Color) maybe it ought to be a new
    direct Object subclass that contains one of each.

    Composition in place of inheritance is often what is needed in these
    cases, rather than kludging the inherited methods to sort-of work.

    Of course, it also depends on whether your design ever needs to use
    ColoredPoints as generic points. Most likely, anywhere it seems to do so
    it really can be changed to operate on myColoredPoint.getPoint().

    More generally, with value-type classes it's generally the case that
    composited ones should be exactly that -- composited. Equality
    comparisons between them rarely make sense, though there are exceptions
    (integers are a subset of fractions, which are a subset of real numbers,
    which are a subset of complex numbers, is the textbook example).

    The other cases where cross-comparisons make much sense tend to be
    collections that have the same semantics but different implementations,
    like the various List implementations, as mentioned elsewhere in this
    thread.

    In any event, warty equals-and-hashCode implementations or thorny
    problems trying to develop these parts of a class tend to indicate the
    need for a refactoring, and often for replacing inheritance with
    composition somewhere up the class hierarchy from the problem class or
    classes.
    zerg, Oct 2, 2008
    #13
  14. zerg wrote:
    > Andreas Leitgeb wrote:
    >> Then the instructor raised the point of deriving a "ColoredPoint"
    >> and showed us the bad effect of the naive approach for overriding
    >> equals (and hashCode()) in ColoredPoint.

    >
    > This sort of situation should induce one to reassess the object
    > relations in an OO design.
    >
    > In particular, ColoredPoint may not make much sense as a "kind of"
    > point, so much as a combination of a point and a color. Which means
    > instead of inheriting from Point (or Color) maybe it ought to be a
    > new
    > direct Object subclass that contains one of each.
    >
    > Composition in place of inheritance is often what is needed in these
    > cases, rather than kludging the inherited methods to sort-of work.
    >
    > Of course, it also depends on whether your design ever needs to use
    > ColoredPoints as generic points. Most likely, anywhere it seems to
    > do
    > so it really can be changed to operate on myColoredPoint.getPoint().
    >
    > More generally, with value-type classes it's generally the case that
    > composited ones should be exactly that -- composited. Equality
    > comparisons between them rarely make sense, though there are
    > exceptions (integers are a subset of fractions, which are a subset
    > of
    > real numbers, which are a subset of complex numbers, is the textbook
    > example).
    > The other cases where cross-comparisons make much sense tend to be
    > collections that have the same semantics but different
    > implementations, like the various List implementations, as mentioned
    > elsewhere in this thread.
    >
    > In any event, warty equals-and-hashCode implementations or thorny
    > problems trying to develop these parts of a class tend to indicate
    > the
    > need for a refactoring, and often for replacing inheritance with
    > composition somewhere up the class hierarchy from the problem class
    > or
    > classes.


    I know I give you a hard time sometimes, but I have to say: this is an
    excellent post, very thorough and well-reasoned. .
    Mike Schilling, Oct 2, 2008
    #14
  15. Tom Anderson <> wrote:
    > My take on this is that subclassing, and overriding equals, is okay, as
    > long as the symmetry of equals is preserved.


    According to Object.equals()'s javadoc:
    The equals method implements an *equivalence relation* on non-null
    object references
    Further down in the docs, transitivity is explicitly required for
    the contract.

    >[transitivity broken]
    > Which could be a problem. Or might not be. It's definitely not pretty, and
    > feels like an accident waiting to happen.

    It's a breach of the contract. It's no better than implementing equals
    as "... { return myAtomicDrivenRandom.randomBoolean(); }" :)

    My fault, that I forgot to mention it as another strong reason against
    sharpening the relation.
    Andreas Leitgeb, Oct 2, 2008
    #15
  16. zerg <> wrote: (with Mike Schilling's applause)
    > Andreas Leitgeb wrote:
    >> Then the instructor raised the point of deriving a "ColoredPoint"
    >> and showed us the bad effect of the naive approach for overriding
    >> equals (and hashCode()) in ColoredPoint.

    >
    > This sort of situation should induce one to reassess the object
    > relations in an OO design.


    You've hit the nail on its head: The conclusion in that lesson was,
    that this design of both-instanciable and subclass-related and both
    custom-equals()ified ... (I hope I haven't forgotten any further
    necessary attributes) ... Point and ColoredPoint was indeed *wrong*.

    Whether the alternative is having Object as lowest common baseclass
    of these classes, or making Point (or some other lowest common baseclass)
    abstract (and derive a MonochromePoint from that, instead, for usage),
    or making Point final (thus prevent the ColoredPoint to derive from
    it), or prevent ColoredPoint from overriding equals(), or ..., or ...
    The point is, that the design was broken, and one shouldn't do it.

    My claim is, that if one needs getClass() to implement .equals() in
    ones class design, then one has made an error some steps earlier.
    An error just like the one in the lesson (where it was made on
    purpose for demonstration, of course).

    Anyone still argueing against this claim?

    If not, we're back to searching for other uses of getClass() in
    "normal" applications, for a specific definition of "normal"
    made up a couple of postings upthread. I still think there is
    none.
    Andreas Leitgeb, Oct 2, 2008
    #16
  17. Lew <> wrote:
    > Andreas Leitgeb wrote:
    >> My claim is, that if one needs getClass() to implement .equals() in
    >> ones class design, then one has made an error some steps earlier.
    >> An error just like the one in the lesson (where it was made on
    >> purpose for demonstration, of course).

    >
    > So you prefer casting the argument from 'Object' to the type?
    > How do you make sure the argument type matches the target type?


    I'm not sure I understand your question. Of course one needs to cast(*)
    the argument to something, if one intends to do anything interesting
    (beyond comparing e.g. toString()-results) in the equals() method.

    *: after first verifying that the cast is legal, per "instanceof".
    (or by catch'ing the ClassCastException).

    Btw., "instanceof" is principially different from getClass(),
    if that was the point of your question.
    Andreas Leitgeb, Oct 2, 2008
    #17
  18. crazzybugger

    Tom Anderson Guest

    On Thu, 2 Oct 2008, Andreas Leitgeb wrote:

    > Tom Anderson <> wrote:
    >> My take on this is that subclassing, and overriding equals, is okay, as
    >> long as the symmetry of equals is preserved.

    >
    > According to Object.equals()'s javadoc:
    > The equals method implements an *equivalence relation* on non-null
    > object references
    > Further down in the docs, transitivity is explicitly required for
    > the contract.


    Sue me! :)

    >> [transitivity broken]
    >> Which could be a problem. Or might not be. It's definitely not pretty, and
    >> feels like an accident waiting to happen.

    > It's a breach of the contract. It's no better than implementing equals
    > as "... { return myAtomicDrivenRandom.randomBoolean(); }" :)


    That's patent nonsense, but i take your point.

    There might well be situations in which you're quite confident that the
    failure of transitivity won't be a problem, but i would readily agree that
    it's a really bad idea for general-purpose classes.

    tom

    --
    What we're dealing with here is a complete lack of respect for the law. --
    Buford T. Justice
    Tom Anderson, Oct 2, 2008
    #18
  19. crazzybugger

    J. Stoever Guest

    Tom Anderson wrote:
    > There might well be situations in which you're quite confident that the
    > failure of transitivity won't be a problem, but i would readily agree
    > that it's a really bad idea for general-purpose classes.


    There might also well be situations in which you're quite confident that
    you have godlike superpowers. Sadly, just because a programmer is
    confident of something doesn't make it so ;)
    J. Stoever, Oct 2, 2008
    #19
  20. crazzybugger

    Lew Guest

    On Oct 2, 9:30 am, "J. Stoever" <> wrote:
    > Tom Anderson wrote:
    > > There might well be situations in which you're quite confident that the
    > > failure of transitivity won't be a problem, but i would readily agree
    > > that it's a really bad idea for general-purpose classes.

    >
    > There might also well be situations in which you're quite confident that
    > you have godlike superpowers. Sadly, just because a programmer is
    > confident of something doesn't make it so ;)


    Cute, but off the point. In fact as a developer of an API, Tom very
    well can be confident of something because he actually did make it so,
    and that was his point. You had it exactly backwards - confidence
    didn't make it safe, making it safe made him confident.

    --
    Lew
    Lew, Oct 2, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Edward A Thompson
    Replies:
    4
    Views:
    516
    Tony Morris
    Feb 11, 2004
  2. kevin
    Replies:
    11
    Views:
    5,782
    Andrew McDonagh
    Jan 8, 2005
  3. Wally Barnes
    Replies:
    3
    Views:
    509
    Wally Barnes
    Nov 20, 2008
  4. Sosuke

    Up casting and down casting

    Sosuke, Dec 20, 2009, in forum: C++
    Replies:
    2
    Views:
    547
    James Kanze
    Dec 20, 2009
  5. javabeginner29
    Replies:
    0
    Views:
    390
    javabeginner29
    Apr 2, 2012
Loading...

Share This Page