Является ли массив примитивным типом или объектом (или чем-то еще)?

Вопрос в принципе не требует пояснений. Мне не удалось найти API для массивов (кроме этого Arrays, но это просто определяет набор статических вспомогательных функций для работы с реальными массивами). Если для него нет класса, это, по-видимому, предполагает, что массив не может быть Object.

Однако тот факт, что массив имеет общедоступные поля, такие как length, и методы, которые он может вызывать, такие как .equals() и .clone(), кажется, предполагает (очень сильно) полную противоположность.

Как объяснить странное представление и поведение примитивных массивов?

В качестве примечания: я только что попытался использовать функцию Eclipse «Открытая реализация» для метода .clone() массива, надеясь, что смогу посмотреть, где и как был определен этот метод (поскольку он сказал, что int[] переопределил его from Object), но на самом деле это привело к зависанию и падению всего моего Eclipse...


person asteri    schedule 09.10.2012    source источник


Ответы (7)


Существует класс для каждого типа массива, поэтому есть класс для int[], есть класс для Foo[]. Эти классы создаются JVM. Вы можете получить к ним доступ с помощью int[].class, Foo[].class. Прямым суперклассом этих классов является Object.class

public static void main(String[] args)
{
    test(int[].class);
    test(String[].class);
}

static void test(Class clazz)
{
    System.out.println(clazz.getName());
    System.out.println(clazz.getSuperclass());
    for(Class face : clazz.getInterfaces())
        System.out.println(face);
}

Существует также правило создания подтипов во время компиляции, если A является подтипом B, A[] является подтипом B[].

person irreputable    schedule 09.10.2012
comment
Отличный ответ! Теперь я понимаю, почему я не мог найти никаких API или чего-то еще. Очень интересно, что JVM сама создает эти классы во время выполнения. И последний вопрос: если массив является членом класса, как и любой другой объект, как работает инициализация? Если то, что вы говорите, верно и [] является лишь частью имени класса, почему они не объявляются с помощью конструктора, то есть new int[](2) vs new int[2]? - person asteri; 10.10.2012
comment
синтаксис int[2] был взят из C, к которому пыталась приблизиться Java. - person irreputable; 10.10.2012
comment
скорее всего, в jvm есть специальный код для обработки инициализации массива, который сильно отличается от стандартного создания объекта. - person Matt; 10.10.2012
comment
Вот о чем я думал. Итак, под капотом компилятор извлекает число и передает его в стандартный конструктор, который он сделал, или что? - person asteri; 10.10.2012
comment
это не должно влиять на выбор синтаксиса. - person irreputable; 10.10.2012
comment
обратите внимание, что правило подтипирования во время компиляции нарушает безопасность типов stackoverflow.com/a/3712419/2558896 - person adam.r; 27.02.2014
comment
Вы не ответили, является ли массив объектом или нет. - person Arun Raaj; 02.08.2018

Спецификация языка Java должна дать вам представление :

Непосредственным суперклассом типа массива является Object.

Каждый тип массива реализует интерфейсы Cloneable и java.io.Serializable.

Кроме того:

Объект — это экземпляр класса или массив.

Таким образом, массивы не являются экземплярами, и поэтому вам не нужен конструктор для их создания. Вместо этого вы используете выражения создания массива.

person Baz    schedule 09.10.2012

См. приведенный ниже код. Он компилирует:

    int[] arr = new int[2];
    System.out.println(arr.toString());

Теперь для любого примитивного типа вы не можете вызвать метод (toString()), определенный в классе Object (или любой метод, если на то пошло)... Итак, массив по сути является Object.

Хорошо, давайте:

Из раздела 4.3 JLS:

Существует четыре типа ссылочных типов: типы классов (§8), интерфейсные типы (§9), переменные типов (§4.4) и типы массивов (§10).

И Раздел 10:

В языке программирования Java массивы являются объектами (§4.3.1), создаются динамически и могут быть присвоены переменным типа Object (§4.3.2). Все методы класса Object могут быть вызваны для массива.

Итак, из первой цитаты Array на самом деле не класс... Это другой тип. Но, по сути, массивы — это объекты, пусть и не какого-то Class, а Array типа. Таким образом, они не являются экземплярами какого-либо класса, и могут быть объекты array определены для создания таким образом...

person Rohit Jain    schedule 09.10.2012
comment
Я знаю. Я использовал массивы раньше. Этот вопрос только что пришел в голову, когда я понял, что массивы ведут себя иначе, чем настоящие обычные объекты. Например, в вашем новом объявлении вы не используете new int[2]()..., потому что это не настоящий конструктор. Почему? Где API? Каково объяснение? Это не так просто, как вы это делаете. - person asteri; 09.10.2012
comment
И я бы предпочел знать, не нравится ли кому-то мой ответ, чтобы я мог его улучшить, а не просто видеть отрицательные голоса. - person Rohit Jain; 09.10.2012

Итак, коротко и просто, да, ‹Type›[] — это тип Object. Он простирается непосредственно от Object, насколько я понимаю. На нем есть все методы Object, toString(), hashCode(), ... Плюс специальная открытая переменная с именем length. Класс java.util.Arrays — это служебный класс для работы с типами массивов. Это немного сбивает с толку, когда вы добавляете к беспорядку такие вещи, как: int[] не наследуется от Object[]. Кроме того, в отличие от других типов Object, для типов массивов нет конструкторов. Они учитывают ключевое слово new, но обычно оно предназначено для выделения размера. Это немного странно, но это всего лишь одна из языковых причуд.

Однако, чтобы ответить на вопрос, да, они являются объектом.

person Greg Giacovelli    schedule 09.10.2012
comment
Массив - это объект... но int[] не наследуется от объекта? Это меня смущает. А еще меня смущает отсутствие конструктора, так как мы используем new... Как это работает? Является ли массив примитивов чем-то средним между объектом и жестко запрограммированным примитивом...? - person asteri; 09.10.2012
comment
no int[] не наследуется от Object[]. Подобно int[] и Object[], String[]... все разные, потому что все они наследуются от Object, а не от Object[]. Обобщения помогают при написании методов, которые принимают массивы, а также служебный класс Arrays, о котором я упоминал, но да, эта странная причуда иногда приводит к некоторому причудливому коду только для того, чтобы типы выровнялись. - person Greg Giacovelli; 09.10.2012
comment
Если int[] не наследуется от Object, а int[] не является примитивом, что это? Является ли основной принцип Java (что все объекты расширяют Object) не совсем верным, и существует ли отдельная категория объектов, к которой относятся массивы? - person asteri; 09.10.2012
comment
Думайте о [] как о части имени класса. Итак, есть int, который является примитивным. Есть Integer, который является Object. И есть int[], другой тип Object. - person Greg Giacovelli; 09.10.2012
comment
Я никогда не говорил, что int[] не наследуется от Object. Пожалуйста, прочитайте еще раз, это тонко, поэтому вы смущены. - person Greg Giacovelli; 09.10.2012
comment
@Jeff Здесь есть некоторая информация . Хотя вопрос направлен на двумерные массивы, ответы на них должны дать вам некоторое представление о механизмах. - person Baz; 09.10.2012
comment
Ах я вижу. Я слишком быстро прочитал твой пост. И спасибо за ссылку, Баз. - person asteri; 09.10.2012
comment
Да, к сожалению, это одна из тех вещей, которые имеют смысл, когда вы действительно садитесь и думаете об этом, но во многих случаях это действительно не очень удобно, как это работает :( К концу этого небольшого препятствия вы никогда не забудете эту концепцию :) - person Greg Giacovelli; 09.10.2012

Массив — это объект-контейнер, который содержит фиксированное количество значений одного типа.

См. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html

person Aleksandr M    schedule 09.10.2012
comment
Я просмотрел эту документацию, но где для нее API? Это то, что я не могу найти нигде. - person asteri; 09.10.2012

Только те несколько примитивных типов в Java, которые мы знаем. По сути, у нас все еще есть несколько шагов для создания массива, таких как объявление, создание или инициализация, если это необходимо, и это означает, что массив действительно является объектом.

Шагнув глубже, примитивные типы могут храниться в памяти с исходными значениями, но объект является адресом (ссылкой). Таким образом, мы можем представить себе парадокс, как мы могли хранить исходные значения в памяти, если массив является примитивным типом? Я думаю так же, как String, но String является окончательным объектом, так что вы можете легко создать объект, String s = "s", как примитивный тип.

person Eric    schedule 09.10.2012

это объект

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html

person Daniel Pereira    schedule 09.10.2012