Тип объекта в Java и ссылки на массивы
public class RefMix {
public static void main(String[] args) {
Object[] a = {null, "foo"};
Object[] b = {"bar", b};
a[0] = b;
System.out.println(a[0][0]);
}
}
Я понимаю, что массивы являются объектами в Java и, следовательно, являются подклассом типа Object. Мое дальнейшее понимание заключается в том, что 2-мерный массив реализуется как массив ссылок на массивы. Поэтому я не понимаю, почему мой a [0] [0] не создает bar
в приведенном выше коде. Вместо этого он не компилируется:
RefMix.java:7: array required, but java.lang.Object found
Ответы
Ответ 1
Я понимаю, что массивы являются объектами в Java и, следовательно, являются подклассом типа Object. Мое дальнейшее понимание заключается в том, что 2-мерный массив реализуется как массив ссылок на массивы.
Это все правильно и объясняет, почему вы можете выполнить назначение
a[0] = b;
без каких-либо жалоб от компилятора.
Поэтому я не понимаю, почему мой a [0] [0] не создает бар в приведенном выше коде.
Хорошо, давайте взглянем на типы в этом выражении:
-
a
- это Object[]
- массив из Object
s
-
a[0]
- это Object
-
a[0][0]
- Теперь вы пытаетесь использовать индекс массива на Object
. Компилятор не знает, что Object
на самом деле является массивом, поэтому он жалуется.
Ответ 2
Тип среды выполнения экземпляра объекта отличается от статически выводимого типа. Компилятор попытается оценить, какой тип каждой переменной может быть в программе, чтобы рано поймать определенные типы ошибок. В этом случае a[0]
всегда будет массивом, но компилятор этого не знает. Поскольку вы получаете объект из массива объектов, все компиляторы знают, что a[0]
является объектом. Поэтому он вызывает ошибку.
В тех случаях, когда вы знаете что-то, всегда будет определенный тип, но компилятор не может понять это, вы можете обойти это, вставив явное приведение.
System.out.println(((Object[])a[0])[0]);
Ответ 3
Вы правы, массивы всегда Objects
в Java, но Objects
не всегда являются массивами, поэтому вы получаете ошибку компиляции, потому что a
является Object[]
(одномерным). Вы не можете получить доступ к
a[0][0];
потому что a
не является двумерным массивом (по крайней мере, он не объявлен как таковой). Однако в этом случае вы уверены, что a[0]
представляет собой массив Objects
. Поэтому вы можете сделать это:
Object[] c = (Object[]) a[0];
System.out.println(c[0]);
// or directly:
System.out.println(((Object[])a[0])[0]);
Этот передает возвращаемый тип a[0]
(который является Object
) в Object[]
, и вы можете получить доступ к "второму слою" массива.
Ответ 4
Поскольку массив в Java является объектом, поэтому первое и второе назначение будут хранить ваш массив как 1-й элемент вашего массива объектов.
Object[] a = {null, "foo"};
Object[] b = {"bar", b};
Теперь вы изменили свой 1-й элемент массива объектов a
, чтобы содержать значение b вместо массива. Но так как это массив объекта. Все, что выходит из него, будет объектом.
Так как a [0] - объект.
Таким образом, вы явно не можете получить доступ к чему-то вроде этого: -
System.out.println(a[0][0]);
Вы можете попытаться привести ваш объект к объекту в массив [0]: -
System.out.println(((Object[])a[0])[0]);
Ответ 5
делать:
System.out.println(((Object[])a[0])[0]);
Это будет "бросать" объект в массив объектов во время выполнения.
Ответ 6
Поскольку в последнее время я много кодирую С++, я обнаружил, что Java гораздо более строг в проверке типов, чем С++. Java видит все, кроме примитивных типов, как Object, но Java делает еще один шаг к тому, чтобы различать типы Array и non-Array. Во время присваивания типа "a [0] = b;", Java сначала проверяет, является ли это типом массива или нет, после чего проходит обычную процедуру проверки полиморфного типа. Если вы хотите, чтобы ваш код работал, вы должны сделать...
Object[][] a = {{null}, {"foo"}};
Object[] b = {"bar", new java.util.Date()};
a[0] = b;
Вы можете увидеть, как java уделяет особое внимание массивам, просматривая подпись Java Class, которая передается классу Class.forName() в качестве параметра. Например, тип данных..
com.foo.Bar[][] barsIn2D;
может быть загружена подписи ниже...
// [ => Array
// [[ => Array of Array type
// L<object>; => Object, not Array
Class.forName("[[Lcom/foo/Bar;");
Как видите, подпись начинается с '[' или 'L'.
Это говорит нам, имеет ли его массив или нет приоритет над "Lcom/foo/Bar;".
Ответ 7
Все, что вы делаете, эквивалентно этому
Object a = {"bar", "foo"};
System.out.println(a[0]);
который тоже не компилируется.