Многомерные массивы в Java расширяют какой класс?

Мне нужно знать, какие именно многомерные массивы классов в 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.

Так может ли кто-нибудь объяснить, что здесь происходит?


person skystar7    schedule 23.02.2010    source источник


Ответы (4)


Многомерный массив в Java — это просто массив массивов (массивов)*.

Кроме того, массивы считаются подклассами Object.

Итак, ваш int[][] - это Object[] (с типом компонента int[]), а также Object (поскольку все массивы являются объектами)

Однако int[] не является Object[] (но все же Object).

Итак, кажется, что двумерные массивы расширяют Object[]

Я не уверен, что "расширить" здесь правильное слово. Массивы занимают особое место в системе типов Java и работают немного иначе, чем другие объекты. Двумерный массив определенно является Object[]. Но если вы спрашиваете о суперклассах, единственный суперкласс, который есть у любого массива, — это Object. Все массивы также являются клонируемыми и сериализуемыми.

person Thilo    schedule 23.02.2010
comment
Лучше сформулировано, чем мой ответ. +1 - person Michael Myers; 23.02.2010
comment
@mmyers: +1 за удаление вашего ответа в пользу того, который, по вашему мнению, был лучше (или так же хорош и раньше). Я желаю, чтобы больше из нас сделал это! - person T.J. Crowder; 23.02.2010
comment
Если мы продолжим, int[][][] является Object[][], так что это своеобразная функция языка java, и для этих массивов нет иерархии классов. - person skystar7; 23.02.2010

Ваше дерево наследования выглядит примерно так:

  1. ref2 является int[][]
  2. ref2 является Object[]
  3. ref2 является Object

Вот фрагмент кода, иллюстрирующий, что я имею в виду:

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

Вы должны увидеть что-то вроде:

ref2: true true
person Bob Cross    schedule 23.02.2010

Массивы в Java ковариантны. Это означает, что TSub[] является подтипом TSuper[], если TSub является подтипом TSuper.

У вас есть int[][], который представляет собой массив int[]. Теперь, как указывали другие, любой массив в Java является подтипом Object, поэтому int[] является подтипом Object. Итак, из-за ковариации массива int[][] является подтипом Object[] (замените TSub = int[] и TSuper = Object в приведенном выше определении ковариации).

Изменить. Чтобы было понятно, почему здесь важна ковариация, учтите, что делать то же самое с List<T> не получится:

List<Object> ref2 = new List<int[]>()
person Ben Lings    schedule 23.02.2010
comment
-1 ваше объяснение сбивает с толку - int не наследуется напрямую от Object - person thecoop; 23.02.2010
comment
Я не говорил, что это так - int[] (массив int) делает. - person Ben Lings; 23.02.2010

Когда мы назначаем

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

компилятор жалуется

Это потому, что int не является подтипом Object, int.class.getSuperclass() возвращает null. Помните, что в Java примитивные значения (целые, длинные, двойные,...) не являются объектами.

Итак, кажется, что двумерные массивы расширяют 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 нарушает принцип подстановки Лискова, потому что

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
person Cephalopod    schedule 16.08.2012