Все мы знаем, что язык программирования Java является чисто объектным языком. Все сущности, с которыми нам приходится иметь дело и осуществлять какие-либо манипуляции, являются объектами (за исключением примитивов), в том числе и массивы. То бишь, если говорить совсем уж простыми словами, то любой массив является конкретным объектом в памяти. Java является сильно типизированным языком. Хоть и градация на языки со слабой и сильной типизацией данных является весьма условной, но Java, так или иначе, больше относится к языкам с сильной типизацией. Это ведёт нас к тому, что все данные имеют свой фиксированный тип (или класс, если говорить в терминах ООП). Вот здесь и вся загвоздка! Мне всегда хотелось узнать, каким образом описываются массивы, как некоторые абстрактные сущности, на физическом уровне. Я понимаю, что невозможно найти готовый класс, в котором бы была описана структура массивов, по той простой причине, что данная сущность является одной из фундаментальных (на равне с примивными типами данных) и её реализация спрятана где-то на уровне JVM или в каком-то другом месте.
Давайте рассмотрим тривиальный пример. Мы знаем, что размер любого массива является фиксированным и определяется на этапе создания самого массива. Сведения о размере массива хранятся в целочисленной переменной с одноимённым названием length. Сразу же возникает вопрос относительно этого поля. Откуда оно взялось? Где можно проследить всю эту внутреннюю логику (если можно так выразиться)? Идём далее. Создали массив в памяти, при этом сразу же указали его размер. Размер массива соответствует количеству однотипных элементов, которые могут храниться в этом массиве. И тут опять-таки вопрос. По какой логике JVM определяет количество элементов, которое нам необходимо? Точнее не совсем так. Понятное дело, что мы сами указываем размер массива, но разве количество полей для отдельно взятого типа данных не должно быть фиксированным?! Есть ли какой-нибудь код (пусть даже псевдокод), который мог бы хоть немного пролить свет на данный вопрос.
Ответ
Надеюсь мой ответ Вам поможет. Также прикрепил ссылки на источники, для подробного изучения.
В Java, массивы являются объектами и наследуются от Object
Переменные в массиве упорядочены, индексация массива начинается с 0.
Когда мы создаем объект массива с помощью new, в куче выделяется под это дело память и возвращает нам ссылку. Но как так получается? Тип массива записывается как type [], где type - тип данных содержащихся элементов; скобки[] - это специальные символы, указывающие, что эта переменная содержит массив; число которое передаем в new int[5] - размер нашего массива.
Что представляет собой массив Java в памяти?
Размер массива не является частью его типа, поэтому скобки пустые
int[] array;
массив объектов будет содержать ссылки на эти объекты, а если он пока не инициализирован, то null (Значения по умолчанию в Java)
Подробнее про массивы можно почитать тут: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
Чтобы подробнее понять как создается массив рассмотрим эквивалентную запись:
String[] array = (String[]) Array.newInstance(String.class, 3);
эта запись равна этой:
String[] array = new String[3];
метод (Class componentType, int length) возвращает нам newArray(componentType, length), а вот уже реализация newArray() является native. И этот прекрасный и скрытый от наших глаз метод возвращает нам наш массив и дальше мы приводим к class [Ljava.lang.String с помощью (String[]) Array.newInstance(String.class, 3).
Ссылки на источники:
https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Array.html
https://www.geeksforgeeks.org/arrays-in-java/
На уровне JVM, на примере int[]
Новый массив целых чисел создается во время выполнения операции
newarray int
Размер массива должен быть в стеке до выполнения этой операции; операция оставляет в стеке ссылку на массив. Ссылки загружаются и сохраняются с помощью операций iaload var и iastore var
Стоит сказать, что на уровне JVM в зависимости от типа будут вызваны соответствующие команды. Подробнее: https://www.artima.com/underthehood/objectsP.html
если ссылка на массив находится в верхней части стека, операция arraylength оставит длину массива поверх стека.
И наверное как раз ее нам возвращает метод Array.getLength(array)
Подробнее:
https://cs.nyu.edu/courses/fall00/V22.0201-001/jvm3.html
Комментариев нет:
Отправить комментарий