2

I wish to overide the equals for int[] arrays. Such that the following will be true

int[] a = {1,2,3};
int[] b = {1,2,3};
System.out.println(a.equals(b));

Is there a way to do that?

Chao Xu
  • 2,156
  • 2
  • 22
  • 31
  • 4
    Wouldn't the simplest approach to be just using [Arrays.equals()](http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html)? – aroth Sep 06 '12 at 03:25
  • 1
    Java does not have any way of overriding operators. It is a very controversial subject in some places, and black-and-white in others, which is why they have chosen to keep it out of the Java language. I honestly wish overriding was allowed to make Java less verbose, but alas, it is not. [This question](http://stackoverflow.com/questions/3598707/operator-overloading-and-overriding-in-java) goes over it in detail. – Jon Egeland Sep 06 '12 at 03:25
  • 1
    HashSet uses equals(), so I can't just make HashSet and check if an array is in there. – Chao Xu Sep 06 '12 at 03:26
  • Also, wouldn't `int[] a = b` make them equal since they would point to the same position in memory? – Jon Egeland Sep 06 '12 at 03:26

4 Answers4

5

Overriding the equals method of int[] is both not possible and not necessary. The functionality you desire can be achieved by using Arrays.equals(int[], int[]).

int[] a = {1,2,3};
int[] b = {1,2,3};
System.out.println(Arrays.equals(a, b));
FThompson
  • 28,352
  • 13
  • 60
  • 93
2

Arrays are low-level constructions of Java, so you can't create sublasses, so you can't override methods. But you can use java.util.List instead of an array. Modern JREs shows the same performance both for arrays and lists.

no id
  • 1,642
  • 3
  • 24
  • 36
  • +1 for using Lists - in particular, an `ArrayList` is almost always preferable to using an array (unless you are writing particularly low-level code) – mikera Sep 06 '12 at 03:43
0

You can't override equals on arrays directly - arrays are a primitive construct in Java and you can't override methods or operators that act on them.

You should consider using ArrayLists instead of arrays - ArrayLists provide an equals() implementation that works as you are looking for (as well as many other useful features that arrays don't have, such as the ability to add new elements to the list etc.)

mikera
  • 105,238
  • 25
  • 256
  • 415
0

The other answers here are correct in that you should really either just use Arrays.equals() or switch to using a List<Integer> instead of an int[].

However, what you want to do is almost possible using reflection and javassist.util.proxy.ProxyFactory. Here's some example code that would do the trick, more or less:

public static void main(String[] args) throws Exception {
    int[] test = {0, 1, 2, 3};
    int[] empty1 = {};
    int[] empty2 = {};

    Class clss = int[].class;
    ProxyFactory factory = new ProxyFactory();
    factory.setSuperclass(clss);
    factory.setFilter(new MethodFilter() {
         public boolean isHandled(Method m) {
             // ignore finalize()
             return !m.getName().equals("finalize");
         }
     });
    factory.setHandler(new IntArrayEqualsHandler());

    Class newArrayClass = factory.createClass();

    int[] specialArray = (int[])newArrayClass.newInstance();
    System.out.println(empty1.equals(empty2));
    System.out.println(specialArray.equals(empty1));
    System.out.println(specialArray.equals(empty2));
    System.out.println(specialArray.equals(test));
}

private static class IntArrayEqualsHandler implements MethodHandler {
    @Override
    public Object invoke(Object thisObj, Method method, Method original, Object[] params) throws Throwable {
        if (method.getName().equals("equals")) {
            int[] left = (int[])thisObj;
            int[] right = (int[])params[0];
            return Arrays.equals(left, right);
        }
        return original.invoke(thisObj, params);
    }

}

Unfortunately, this won't work because int[].class is declared as final in the language, so even using reflection it cannot be extended. At least as far as I can tell. There are tricks you can pull to remove the 'final' modifier from a field, but there doesn't seem to be an equivalent hack available for removing the final modifier from an entire class.

If there was such a thing, you could use the code above, or something like it, to generate a custom subclass of int[] at runtime that implemented your desired equals() behavior.

Really though that's all more trouble than it's worth, especially when you start looking at how to actually use the custom subclass in the rest of your project. So all things considered you are much better off just using Arrays.equals() or List<Integer>.

Community
  • 1
  • 1
aroth
  • 54,026
  • 20
  • 135
  • 176