为什么 Arrays.deepEquals(Object[]arr1,Object[]arr2) 适用于 int[][] ,float[][] 等原始多维数组?

问题描述 投票:0回答:2

从方法签名可以很清楚地看出,该方法接受类型为 Object[] 的参数,但该方法对于原始多维数组仍然工作得很好?(如 int[][]、float[][] 等) (但是它显示原始一维数组的错误(如 int[]、float[] 等))

例如:

      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[])"*/

同样的问题是 Arrays.deepToString(Object[]) 从方法签名中可以清楚地看出,该方法也接受 Object[] 类型的参数,但对于原始多维数组仍然可以正常工作?(如 int[][ ],float[][] 等)(但是它显示原始一维数组的错误(如 int[],float[] 等))

  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[])"

编辑:

我也想补充几点。

1:Java 中的子类型:

What is subtyping?

=>子类型是面向对象的一个关键特性 Java 等编程语言。在 Java 中,如果 S 是 T 的子类型 扩展或实现 T。子类型化是可传递的,这意味着如果 R 是一个 S 的子类型,则 R 也是 T 的子类型(T 是两者的超类型 沙R).String是Object的子类型,因为String类是一个 Object 类的子类。

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:数组类型之间的子类型化:

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:数组类型的直接超类是 Object。

4:每个数组类型都实现接口 Cloneable 和 java.io.Serializable.

5:在Java编程语言中,数组是对象,是动态的 创建并可以分配给 Object 类型的变量。的所有方法 可以在数组上调用类对象。

6:对象是类实例或数组。

7:参考值(通常只是引用)是指向这些的指针 对象,以及一个特殊的空引用,它不引用任何对象。

8:类实例由类实例显式创建 创作表达。

9:数组是由数组创建表达式显式创建的。

java arrays multidimensional-array primitive deepequals
2个回答
2
投票

问的字面问题是:

为什么

Arrays.deepEquals(Object[] arr1, Object[] arr2)
适用于像
int[][]
float[][]
等原始多维数组?

对此的简单回答是“因为 javadoc 是这么说的”。详见@老狗程序员的回答


但是被问到的real问题(据我所知)是:

为什么它适用于

int[][]
float[][]
等但不适用于
int[]
float[]
等?

这是子类型化和多维数组类型在 Java 中工作方式的结果。在 Java 中确实没有多维数组类型1。例如,

int[][]
类型实际上是一个“
int
的数组的数组”。 “
int
的数组”部分是原始数组类型。

根据Java子类型规则,所有数组(包括一维原始数组如

int[]
)都是
Object
的子类型。这意味着
int[][]
(“
int
的数组的数组”)是
Object[]
(“
Object
的数组”)的子类型。

相比之下,

int[]
不是
Object[]
的子类型,因为
int
不是
Object
的子类型。

这意味着

Arrays.deepEquals
不适用于原始数组(即该方法不适用于参数)但它确实适用于 arrays of 原始数组;即多维原始数组。实际的解决方案是在比较一维原始数组时使用
Arrays.equals
重载。


1 - JLS 第 1 章指出:“该语言支持数组的数组,而不是多维数组。”


0
投票

之所以有效,是因为

Arrays.deepEquals
是为二维基元数组而编写的。 API 指定它将起作用。这是引用,其中我强调了最相关的行:

如果满足以下任何条件,则两个可能为空的元素 e1 和 e2 深度相等:

  • e1 和 e2 都是对象引用类型的数组,Arrays.deepEquals(e1, e2) 将返回 true
  • e1 和 e2 是相同原始类型的数组,适当重载 Arrays.equals(e1, e2) 将返回 true。
  • e1 == e2
  • e1.equals(e2) 将返回 true。 请注意,此定义允许任何深度的空元素。

它是如何工作的?我们可以查看该方法的源代码。它包含一个

if ... else
链,用于检查每个参数是否都是 an
instanceof
相同类型的原始数组。

deepToString
方法的代码包含一个类似的
if ... else
链。

© www.soinside.com 2019 - 2024. All rights reserved.