Создание класса массива java

Как создать массив объектов класса java

Для создания массива объектов класса в Java можно использовать следующий синтаксис:

ClassName[] array = new ClassName[size]; 

Где ClassName — имя класса, а size — количество элементов в массиве. Затем можно инициализировать каждый элемент массива, создавая новые объекты с помощью оператора new:

array[0] = new ClassName(); array[1] = new ClassName(); // и т.д. 

Можно также использовать цикл for для инициализации всех элементов массива:

for (int i = 0; i  size; i++)  array[i] = new ClassName(); > 

Вместо пустого конструктора можно передать аргументы в конструктор класса для создания объектов с определенными значениями.

Источник

Массив объектов в Java

Массив объектов в Java_vertex

Ранее на нашем сайте уже была размещена статья, посвященная массивам в Java. В ней мы рассказывали, что массив — это такой » контейнер «, который может вмещать в себя несколько однородных переменных.

Массив объектов в Java_vertex

У массивов есть несколько особенностей:

1. Они могут хранить переменные только одного типа ;

2. Размер массива нельзя поменять;

4. Элементы массивов имеют индексы, по которым к ним и обращаются в случае необходимости;

5. Номер первого элемента массива — 0 ;

6. Можно создавать пустые массивы, и «положить» в них элементы потом .

А вот что такое «массивы объектов» мы ранее не рассматривали. Давайте разберемся что к чему.

Массив объектов

По сути, у массивов объектов очень много общего с обычными массивами, только у них другая «начинка». Тем не менее, как Вы знаете, объекты гораздо «сложнее», чем переменные, потому что у них есть больше составляющих.

Массив объектов объявляется так же, как и массив переменных:

Как вы видите, у нас не массив разных объектов (стульев, столов и жевательных резинок). Это массив объектов одного класса (массив стульев, например).

Тут тоже все начинается и заканчивается названием класса , а в конце в квадратных скобках указывается размер массива:

Распространенная ошибка

Массив объектов отличается одной особенностью — они состоят из ссылок на объекты:

Массив объектов в Java_vertex

То есть в массиве не содержатся все переменные и методы каждого объекта, как Вы могли бы подумать, а только ссылки на эти самые объекты. Но тут возникает одна опасность. Обычно переменные в массивах имеют значения по умолчанию — если не задать, например, значение переменной int, то она по умолчанию будет равна 0 (больше информации про значения по умолчанию можно найти здесь).

В случает с объектами, происходит по-другому. В массиве должна храниться ссылка на объект, но пока объекта не существует, — ссылки на него тоже быть не может .

Поэтому, в массиве хранится значение по умолчанию null. Если Вы попробуете вызвать метод не созданного объекта, возникнет распространенная ошибка NullPointerException . Обязательно создайте свои объекты перед тем, как обращаться к ним! 😉

Пример

Давайте создадим массив объектов. Допустим, у нас есть класс — ObjMass, и все, что в нем хранится — это массив объектов Cat из 3 элементов:

Источник

Кофе-брейк #130. Как правильно работать с массивами Java — советы от Oracle

Java-университет

Кофе-брейк #130. Как правильно работать с массивами Java — советы от Oracle - 1

Источник: Oracle Работа с массивами может включать в себя отражение, дженерики и лямбда-выражения. Недавно я разговаривал с коллегой, который занимается разработкой на языке C. Разговор зашел о массивах и о том, как они работают в Java по сравнению с C. Я нашел это немного странным, учитывая, что Java считается С-подобным языком. В них действительности много схожего, но есть и отличия. Давайте начнем с простого.

Объявление массива

Если следовать учебнику по Java, то вы увидите, что существует два способа объявить массив. Первый прямолинеен:

 int[] array; // a Java array declaration 
 int array[]; // a C array declaration 
 array = new int[10]; // Java array allocation 

Что делать, если вы не знаете значения? Вот код, с которым вы будете сталкиваться чаще всего для объявления, выделения и использования массива int :

 int[] array; array = new int[10]; array[0] = 0; array[1] = 1; array[2] = 1; array[3] = 2; array[4] = 3; array[5] = 5; array[6] = 8; . 

Обратите внимание, что я указал массив int , который представляет собой массив примитивных типов данных (primitive data types) Java. Давайте посмотрим, что произойдет, если вы попробуете выполнить тот же процесс с массивом объектов Java вместо примитивов:

 class SomeClass < int val; // … >SomeClass[] array = new SomeClass[10]; array[0].val = 0; array[1].val = 1; array[2].val = 1; array[3].val = 2; array[4].val = 3; array[5].val = 5; array[6].val = 8; 

Если запустить приведенный выше код, то мы получим исключение сразу после попытки использовать первый элемент массива. Почему? Несмотря на то, что массив выделен, каждый сегмент массива содержит пустые ссылки на объекты. Если вы введете этот код в свою IDE, он даже автоматически заполнит .val для вас, поэтому ошибка может сбивать с толку. Чтобы устранить баг, выполните следующие действия:

 SomeClass[] array = new SomeClass[10]; for ( int i = 0; i < array.length; i++ ) < //new code array[i] = new SomeClass(); //new code >//new code array[0].val = 0; array[1].val = 1; array[2].val = 1; array[3].val = 2; array[4].val = 3; array[5].val = 5; array[6].val = 8; 

Но это не элегантно. Я задумался, почему я не могу легко выделить массив и объекты внутри массива, написав меньше кода, может даже все в одной строке. Чтобы найти ответ, я провел несколько экспериментов.

В поисках нирваны среди массивов Java

Наша цель — кодить элегантно. Следуя правилам “чистого кода”, я решил создать код многократного использования, чтобы очистить шаблон распределения массива. Вот первая попытка:

 public class MyArray < public static Object[] toArray(Class cls, int size) throws Exception < Constructor ctor = cls.getConstructors()[0]; Object[] objects = new Object[size]; for ( int i = 0; i < size; i++ ) < objects[i] = ctor.newInstance(); >return objects; > public static void main(String[] args) throws Exception < SomeClass[] array1 = (SomeClass[])MyArray.toArray(SomeClass.class, 32); // see this System.out.println(array1); >> 

Строка кода, помеченная как “see this”, выглядит именно так, как я хотел, благодаря реализации toArray . Этот подход использует отражение, чтобы найти конструктор по умолчанию для предоставленного класса, а затем вызывает этот конструктор для создания экземпляра объекта этого класса. Процесс вызывает конструктор один раз для каждого элемента массива. Великолепно! Жаль только, что это не работает. Код компилируется нормально, но приводит к ошибке ClassCastException при запуске. Чтобы использовать этот код, вам нужно создать массив Object элементов, а затем привести каждый элемент массива к классу SomeClass следующим образом:

 Object[] objects = MyArray.toArray(SomeClass.class, 32); SomeClass scObj = (SomeClass)objects[0]; . 

Это не элегантно! После дополнительных экспериментов я разработал несколько решений, использующих отражение, дженерики и лямбда-выражения.

Решение 1. Используйте отражение

Здесь мы используем класс java.lang.reflect.Array для создания экземпляра массива указанного вами класса вместо использования базового класса java.lang.Object . По сути это однострочное изменение кода:

 public static Object[] toArray(Class cls, int size) throws Exception < Constructor ctor = cls.getConstructors()[0]; Object array = Array.newInstance(cls, size); // new code for ( int i = 0; i < size; i++ ) < Array.set(array, i, ctor.newInstance()); // new code >return (Object[])array; > 

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

 SomeClass[] array1 = (SomeClass[])MyArray.toArray(SomeClass.class, 32); 

Хотя это не обязательное изменение, вторая строка была изменена, чтобы использовать класс отражения Array для установки содержимого каждого элемента массива. Это замечательно! Но есть еще одна деталь, которая кажется не совсем правильной: приведение к SomeClass[] не очень красиво выглядит. К счастью, есть решение с дженериками.

Решение 2. Используйте дженерики

Фреймворк Collections использует дженерики для привязки к типу и устраняет приведения к ним во многих своих операциях. Здесь также можно использовать дженерики. Возьмем, например, java.util.List.

 List list = new ArrayList(); list.add( new SomeClass() ); SomeClass sc = list.get(0); // Error, needs a cast unless. 

Третья строка в приведенном выше фрагменте вызовет ошибку, если вы не обновите первую строку следующим образом:

 public class MyArray  < public E[] toArray(Class cls, int size) throws Exception < E[] array = (E[])Array.newInstance(cls, size); Constructor ctor = cls.getConstructors()[0]; for ( int element = 0; element < array.length; element++ ) < Array.set(array, element, ctor.newInstance()); >return arrayOfGenericType; > > // . MyArray a1 = new MyArray(SomeClass.class, 32); SomeClass[] array1 = a1.toArray(); 

Это выглядит хорошо. Используя дженерики и включив целевой тип в объявление, тип можно вывести в других операциях. Кроме того, этот код можно сократить до одной строки, если сделать вот так:

 SomeClass[] array = new MyArray(SomeClass.class, 32).toArray(); 

Миссия выполнена, верно? Ну, не совсем. Это нормально, если вам все равно, какой конструктор класса вы вызываете, но если вы хотите вызвать конкретный конструктор, то это решение не работает. Вы можете продолжать использовать отражение для решения этой проблемы, но тогда код станет сложным. К счастью, существуют лямбда-выражения, которые предлагают другое решение.

Решение 3. Используйте лямбда-выражения

Признаюсь, раньше меня не особо вдохновляли лямбда-выражения, но потом я научился ценить их. В частности, мне понравился интерфейс java.util.stream.Stream, обрабатывающий наборы объектов. Stream помог мне достичь нирваны среди массивов Java. Вот моя первая попытка использовать лямбды:

 SomeClass[] array = Stream.generate(() -> new SomeClass()) .toArray(SomeClass[]::new); 

Я разбил этот код на три строки для удобства чтения. Вы можете увидеть, что он соответствует всем требованиям: он прост и элегантен, создает заполненный массив экземпляров объектов и позволяет вызывать определенный конструктор. Обратите внимание на параметр метода toArray : SomeClass[]::new . Это функция-генератор, используемая для выделения массива указанного типа. Однако в его нынешнем виде у этого кода есть небольшая проблема: он создает массив бесконечного размера. Это не слишком оптимально. Но проблему можно решить, вызвав метод limit :

 SomeClass[] array = Stream.generate(() -> new SomeClass()) .limit(32) // calling the limit method .toArray(SomeClass[]::new); 

Массив теперь ограничен 32 элементами. Вы даже можете установить определенные значения объекта для каждого элемента массива, как показано ниже:

 SomeClass[] array = Stream.generate(() -> < SomeClass result = new SomeClass(); result.val = 16; return result; >) .limit(32) .toArray(SomeClass[]::new); 

Этот код демонстрирует эффективность лямбда-выражений, но код не является аккуратным и компактным. На мой взгляд, вызов другого конструктора для установки значения будет намного лучше.

 SomeClass[] array6 = Stream.generate( () -> new SomeClass(16) ) .limit(32) .toArray(SomeClass[]::new); 

Мне нравится решение на основе лямбда-выражения. Оно идеально подходит, когда вам нужно вызвать конкретный конструктор или работать с каждым элементом массива. Когда мне нужно что-то более простое, я обычно использую решение, основанное на дженериках, поскольку оно проще. Однако вы сами можете видеть, что лямбда-выражения представляют собой элегантное и гибкое решение.

Заключение

Сегодня мы узнали, как в Java работать с объявлением и выделением массивов примитивов, выделять массивы элементов Object , использовать отражение, дженерики и лямбда-выражения.

Источник

Читайте также:  Python work with serial
Оцените статью