views:

212

answers:

3

Hi,

I'd like my EqualTester generic class to call the overridden equals(...) method of its generic parameter, but it seems to call Object.equals instead. Here is my test code:

import junit.framework.TestCase;

public class EqualityInsideGenerics extends TestCase {

    public static class EqualTester<V> {
        public boolean check(V v1, V v2) {
            return v1.equals(v2);
        }
    }

    public static class K {
        private int i;
        private Object o;

        public K(Object o, int i) {
            this.o = o;
            this.i = i;
        }
        public boolean equals(K k) {
            return ((k.o != null && k.o.equals(o)) || o == null) && (k.i == i);
        }
    };

    public void testEqual() {
        K k1 = new K(null, 0);
        K k2 = new K(null, 0);
        assertTrue(k1.equals(k2));          // This one ok
        EqualTester<K> tester = new EqualTester<K>();
        assertTrue(tester.check(k1, k2));   // This one KO!
    }
}

Could you please explain why this does not work, and how I could change my EqualTester class?

Is it because K does not actually override the Object.equals() method (because the parameter does not have the correct type)?

Thanks.

+6  A: 

You need to code as public boolean equals(Object k)
and then cast to K
Right now you are just overloading the equals method.
Its also useful to add @Override to the methods, this'll help trouble later. When overriding the method signature must match exactly.

Padmarag
+3  A: 

Because equals(K k) does not actually override the equals(Object o) method.

You must override equals(Object o) exactly in order for it to work.

Phill Sacre
A: 

Thanks Padmarag and Phill!

A solution that works:

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof K)) {
            return false;
        }
        K k = (K)obj;
        return ((k.o != null && k.o.equals(o)) || o == null) && (k.i == i);
    }

Comments welcome: I started programming in Java only a few days ago...

Xavier Nodet
Glad that I could be of help.If you want some more advanced (and tricky) information, try this link - http://www.artima.com/lejava/articles/equality.html
Padmarag
Also use instanceof before casting, then you won't need the ClassCastException try block.
Padmarag
Done! Thanks...
Xavier Nodet
This is an area where a good static analysis tool can help you. I thoroughly recommend using Findbugs, which would have detected this error, and given detail about why it's an error.
Grundlefleck