Search code examples
javaarraysmultidimensional-arrayprimitivedeepequals

Why does Arrays.deepEquals(Object[]arr1,Object[]arr2) works for primitive multidimensional arrays like int[][] ,float[][] etc?


From method signature it is very clear that method accepts the argument of type Object[] but still this method works perfectly fine for primitive multidimensional arrays ?(like int[][],float[][] etc) (However it shows error for primitive one dimensional array (like int[],float[] etc))

Ex:

      int[][]arr=new int[2][3];
      arr[0][0]=1;
      arr[0][1]=2;
      arr[0][2]=3;
      arr[1][0]=4;
      arr[1][1]=5;
      arr[1][2]=6;
      int[][]arr1=new int[2][3];
      arr1[0][0]=1;
      arr1[0][1]=2;
      arr1[0][2]=3;
      arr1[1][0]=4;
      arr1[1][1]=5;
      arr1[1][2]=6;

      System.out.println(Arrays.deepEquals(arr,arr1));

      Output: true


Ex:  
     int[]arr={1,2,3,4,5};
     int[]arr1={1,2,3,4,5};
     System.out.println(Arrays.deepEquals(arr,arr1));//Error
/*"The method deepEquals(Object[], Object[]) in the type Arrays is not applicable for the arguments (int[], int[])"*/

the same issue is with Arrays.deepToString(Object[]) From method signature it is very clear that this method too accepts the argument of type Object[] but still it works perfectly fine for primitive multidimensional arrays ?(like int[][],float[][] etc)(However it shows error for primitive one dimensional array (like int[],float[] etc))

  Ex:
      int[][]arr=new int[2][3];
      arr[0][0]=1;
      arr[0][1]=2;
      arr[0][2]=3;
      arr[1][0]=4;
      arr[1][1]=5;
      arr[1][2]=6;

      System.out.println(Arrays.deepToString(arr));

      Output: [[1, 3, 0], [4, 5, 6]]


 Ex:

     int[]arr={1,2,3,4,5}; 
     System.out.println(Arrays.deepToString(arr)); //Error
    //"The method deepToString(Object[]) in the type Arrays is not applicable for the arguments (int[])"

Edit:

I would also like to add few points from my end as well.

1: Subtyping in Java :

What is subtyping?

=>Subtyping is a key feature of object-oriented programming languages such as Java. In Java, Sis a subtype of T if S extends or implements T. Subtyping is transitive, meaning that if R is a subtype of S, then R is also a subtype of T (T is the super type of both Sand R).String is a subtype of Object, because the String class is a subclass of the Object class.

int is not a subtype of Object, because none of Java's primitive types 
are subtypes of any reference type.

StringBuilder is not a subtype of String, because the StringBuilder 
class is not a subclass of the String class.

 HashMap<Candidate,Double> is a subtype of Map<Candidate,Double>, 
 because the HashMap class implements the Map interface and the type 
 parameters match.

 HashMap<Candidate,Double> is not a subtype of Map<String,Ballot>, even 
 though the HashMap class implements the Map interface, because the type 
 parameters do not match.

2: Subtyping among Array Types :

The following rules define the direct supertype relation among array 
types:

If S and T are both reference types, then S[] >1 T[] iff S >1 T.

Object >1 Object[]

Cloneable >1 Object[]

java.io.Serializable >1 Object[]

If P is a primitive type, then:

Object >1 P[]

Cloneable >1 P[]

java.io.Serializable >1 P[]

3: The direct superclass of an array type is Object.

4: Every array type implements the interfaces Cloneable and java.io.Serializable.

5:In the Java programming language, arrays are objects , are dynamically created, and may be assigned to variables of type Object. All methods of class Object may be invoked on an array.

6: An object is a class instance or an array.

7: The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.

8: A class instance is explicitly created by a class instance creation expression.

9: An array is explicitly created by an array creation expression .


Solution

  • The literal question asked is:

    Why does Arrays.deepEquals(Object[] arr1, Object[] arr2) work for primitive multidimensional arrays like int[][], float[][] etc?

    The simple answer to that is "because the javadoc says so". See @Old Dog Programmer's answer for details.


    But the real question being asked (as I understand it) is:

    Why does it work for int[][], float[][] etc but not for int[], float[] etc?

    This is a consequence of the way that subtyping and multidimensional array types work in Java. In Java there is really no such thing as a multidimensional array type1. For example, the type int[][] is actually an "array of arrays of int". The "array of int" part is a primitive array type.

    According to the Java subtyping rules, all arrays (including 1-D primitive arrays such as int[]) are subtypes of Object. That means that int[][] ("array of arrays of int") is a subtype of Object[] ("array of Object").

    By contrast an int[] is NOT a subtype of Object[] since int is not a subtype of Object.

    That means that Arrays.deepEquals doesn't work for primitive arrays (i.e. the method is not applicable to the arguments) but it does work for arrays of primitive arrays; i.e. multidimensional primitive arrays. The practical solution is to use the Arrays.equals overloads when comparing 1-D primitive arrays.


    1 - JLS Chapter 1 states: "The language supports arrays of arrays, rather than multidimensional arrays."