4

A multipurpose field in an Object of type ObjectHolder contains an Object obj. obj might store a wrapped primitive or an array of primitives. How can we compare two objs if they are arrays? A simplified example:

import java.util.Arrays;

public class ObjectHolder {

    public Object obj;

    public static void main(String[] args) {

        ObjectHolder oh1 = new ObjectHolder();
        oh1.obj = new int[]{ 3, 4, 5 };

        ObjectHolder oh2 = new ObjectHolder();
        oh2.obj = new int[]{ 3, 4, 5 };

        if (oh1.obj.getClass().isArray() && oh2.obj.getClass().isArray()) {
            System.out.println("We know both objects are arrays.");
            // System.out.println(Arrays.equals(oh1.obj, oh2.obj));
        }   
    }   

}   

The commented-out line causes the compile to break.

Note- the array can be of any primitive type (or String), so simply casting it to int[] is not a convenient general solution.

user365904
  • 43
  • 3
  • 1
    Possible duplicate of [Comparing two integer arrays in java](http://stackoverflow.com/questions/14897366/comparing-two-integer-arrays-in-java) – Tibrogargan Oct 13 '16 at 20:13
  • In which java version is this? I can't seem to find it – ItamarG3 Oct 13 '16 at 20:13
  • 1
    @Tibrogargan - I don't think so, here he's talking about ObjectHolder – ItamarG3 Oct 13 '16 at 20:14
  • @ItamarGreen Yes, he is: "How can we compare two objs if they are arrays?". The ObjectHolder piece he's already got – Tibrogargan Oct 13 '16 at 20:15
  • What's the point in a class to hold an `Object` reference? Doesn't an `Object` reference already do that? – Andy Turner Oct 13 '16 at 20:15
  • Oh, I see what you mean. – ItamarG3 Oct 13 '16 at 20:16
  • 1
    @Tibrogargan You're missing the point that the arrays might not *be* `int[]` objects. They could be `float[]`, `boolean[]`, `String[]`, `Object[]`, `Long[]`, or anything else you can imagine. Read the last sentence of the question: *Note- the array can be of **any primitive type (or String)**, so simply casting it to int[] is not a convenient general solution.* – Andreas Oct 13 '16 at 20:16
  • @AndyTurner Holders provide a means to return values from a method that also needs to return other values and/or return a success/failure. i..e `ObjectHolder h = new ObjectHolder(); if (foo(h)) { ... doSomething(h.object); }` – Tibrogargan Oct 13 '16 at 22:28

2 Answers2

2

Next, you verify that the arrays have the same component type by calling getComponentType(), then call the appropriate overload of Arrays.equals() (there are 9 of them).

UPDATED

Of course, it would be much easier to just call Arrays.deepEquals(Object[] a1, Object[] a2), since it already has all the logic of doing that.

if (Arrays.deepEquals(new Object[] { oh1.obj }, new Object[] { oh2.obj })) {
    // They are equal, though they may not be arrays
}

To quote the javadoc, where e1 = oh1.obj and e2 = oh2.obj:

  • e1 and e2 are both arrays of object reference types, and Arrays.deepEquals(e1, e2) would return true
  • e1 and e2 are arrays of the same primitive type, and the appropriate overloading of Arrays.equals(e1, e2) would return true.
  • e1 == e2
  • e1.equals(e2) would return true.
Andreas
  • 154,647
  • 11
  • 152
  • 247
2

In this case Java Reflections will do the job (idea from question Java Array Comparison):

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class ObjectHolder {
    public Object obj;

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {

        ObjectHolder oh1 = new ObjectHolder();
        oh1.obj = new int[] { 3, 4, 5 };

        ObjectHolder oh2 = new ObjectHolder();
        oh2.obj = new int[] { 3, 4, 6 };

        if (oh1.obj.getClass().isArray() && oh1.obj.getClass().equals(oh2.obj.getClass())) {
            Class<?> c = oh1.obj.getClass();

            if (!c.getComponentType().isPrimitive()) {
                c = Object[].class;
            }

            Method m = Arrays.class.getMethod("deepEquals", c, c);
            System.out.println((Boolean) m.invoke(null, oh1.obj, oh2.obj));
        }
    }
}

Update

I think the way @Andreas pointed out in his edited answer the following way might be a shorter, better and cleaner solution than using Java Reflections:

if(oh1.obj.getClass().isArray() && oh1.obj.getClass().equals(oh2.obj.getClass())) {
    System.out.println(Arrays.deepEquals(new Object[] { oh1.obj }, new Object[] { oh2.obj }))
}
Community
  • 1
  • 1
M. Birkholz
  • 63
  • 1
  • 7