【问题标题】:Multidimensional arrays in Java extends which class?Java中的多维数组扩展了哪个类?
【发布时间】:2011-01-20 03:43:20
【问题描述】:

我需要知道 Java 中的哪个类多维数组精确扩展?

当我们分配时

Object[] ref=new int[]{1,2,3};

编译器抱怨对象是不同的类型。所以看起来一维数组扩展Object;我已经知道了。

但是我们分配的时候

Object[] ref2=new int[][]{{1,2,3},{4,5,6}};

编译器不会抱怨。所以看起来二维数组扩展了Object[]

但是当我打印它的超类名称时:

System.out.println(ref2.getClass().getSuperclass().getName());

我收到了java.lang.Object

那么谁能解释一下这里发生了什么?

【问题讨论】:

    标签: java arrays multidimensional-array


    【解决方案1】:

    Java 中的多维数组实际上只是一个数组(数组)*。

    此外,数组被认为是 Object 的子类。

    所以,您的int[][]Object[](组件类型为int[]),也是Object(因为所有数组都是对象)

    然而int[] 不是Object[](但它仍然是Object)。

    所以看起来二维数组扩展了 Object[]

    我不确定“扩展”在这里是否合适。数组在 Java 类型系统中具有特殊的地位,并且与其他对象的工作方式略有不同。二维数组绝对是 Object[]。但是如果你问的是超类,那么任何类型的数组唯一的超类就是 Object。所有数组也是可克隆和可序列化的。

    【讨论】:

    • 措辞比我的回答更好。 +1
    • @mmyers:+1 删除您的答案,转而支持您认为更好(或同样好和更快)的答案。我希望我们中的更多人这样做!
    • 如果我们继续 int[][][] 是一个 Object[][],所以它是 java 语言中的一种特性,并且这些数组没有类层次结构。
    【解决方案2】:

    您的继承树如下所示:

    1. ref2 is-a int[][]
    2. ref2 is-a Object[]
    3. ref2 is-a Object

    这是一个说明我的意思的代码片段:

    Object ref2 = new int[][]{{1,2,3}, {4,5,6}};
    System.err.println("ref2: " + (ref2 instanceof int[][]) + 
      " " + (ref2 instanceof Object[]));
    

    您应该会看到如下内容:

    ref2: true true
    

    【讨论】:

      【解决方案3】:

      Java 中的数组是协变的。这意味着如果TSubTSuper 的子类型,则TSub[]TSuper[] 的子类型。

      您有int[][],它是int[] 的数组。现在,正如其他人指出的那样,Java 中的任何数组都是Object 的子类型,所以int[]Object 的子类型。所以,由于数组协方差,int[][]Object[] 的子类型(在上面的协方差定义中替换TSub = int[]TSuper = Object)。

      编辑 - 要清楚为什么协方差在这里很重要,请考虑用 List<T> 做同样的事情是行不通的:

      List<Object> ref2 = new List<int[]>()
      

      【讨论】:

      • -1 你的解释令人困惑 - int 不直接继承 Object
      • 我没说是 - int[] (array of int) 是。
      【解决方案4】:

      当我们分配时

      Object[] ref=new int[]{1,2,3};
      

      编译器抱怨

      这是因为int 不是Object 的子类型,int.class.getSuperclass() 返回null。请记住,在 Java 中,原始值(ints、longs、doubles、...)不是对象。

      所以二维数组似乎扩展了 Object[]。
      但是当我打印它的超类名称时:

       System.out.println(ref2.getClass().getSuperclass().getName());  
      

      我得到了 java.lang.Object。

      数组更像接口,因为它们进行多重继承。但它们不是真正的接口,就 Java 接口而言。

      class A {}
      interface I {}
      class B extends A implements I {}
      
      
      B[][] bArray = new B[1][1];
      System.out.println(bArray instanceof A[][]);
      System.out.println(bArray instanceof I[][]);
      System.out.println(bArray instanceof Object[]);
      System.out.println(bArray.getClass().getSuperclass());
      for (Class i: bArray.getClass().getInterfaces())
          System.out.println(i);
      System.out.println(I[][].class.isAssignableFrom(bArray.getClass()));
      System.out.println(I[][].class.isInstance(bArray));
      

      输出:

      true
      true
      true
      class java.lang.Object
      interface java.lang.Cloneable
      interface java.io.Serializable
      true
      true
      

      此外,Java 违反了 Liskov 替换原则,因为

      B[] bArray = new B[1];
      A[] aArray = bArray;
      // bArray[0] = new A(); // causes a compile error
      aArray[0] = new A(); // compiles, but causes runtime exception
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-14
        • 2013-04-19
        • 1970-01-01
        • 1970-01-01
        • 2017-04-05
        • 1970-01-01
        • 2016-01-15
        相关资源
        最近更新 更多