Масив от обекти в Java
⚡ Умно обобщение
Масив от обекти в Java съхранява референции към обекти в съседен слот с фиксиран размер, позволявайки на една променлива да съхранява много екземпляри на клас и да осъществява достъп до всеки един чрез индекс за итерация, мутация и предаване на методи.
Какво е масив от обекти в Java?
A Java масив от обекти съхранява множество екземпляри на обекти от един и същи клас в един контейнер с фиксиран размер. За разлика от примитивен масив, който съхранява стойности като int, double или boolean директно във всеки слот се съхранява масив от обекти препраткиВсеки слот сочи към местоположението в паметта на обект, а самият обект се намира там. Java купчина.
Това оформление съответства на начина, по който всеки обект променлив in Java работи. Масивът просто групира няколко обектни препратки заедно, така че да можете да достъпвате до тях по индекс. Това е естественият избор, когато броят на обектите е известен предварително и не се променя по време на жизнения цикъл на програмата.
Синтаксис
ClassName[] obj = new ClassName[array_length];
Дясната страна отделя място за array_length препратки, всички инициализирани към nullНяма обект на ClassName все още съществува, само контейнерът, който може да съдържа препратки към такива обекти.
Как да създадете масив от обекти в Java
Създаването на работещ масив от обекти винаги отнема две стъпки за разпределение. Първата разпределя контейнера за референтни данни, а втората разпределя всеки обект, към който контейнерът ще сочи. Пропусканеping втората стъпка е най-често срещаният източник на NullPointerException за начинаещи Java код.
Стъпка 1) Отворете си кода редактор и копирайте следния код:
class ObjectArray { public static void main(String args[]) { Account obj[] = new Account[2]; // obj[0] = new Account(); // obj[1] = new Account(); obj[0].setData(1, 2); obj[1].setData(3, 4); System.out.println("For Array Element 0"); obj[0].showData(); System.out.println("For Array Element 1"); obj[1].showData(); } } class Account { int a; int b; public void setData(int c, int d) { a = c; b = d; } public void showData() { System.out.println("Value of a = " + a); System.out.println("Value of b = " + b); } }
Стъпка 2) Запазете файла като ObjectArray.java, след което го компилирайте и стартирайте.
Стъпка 3) Обърнете внимание на грешката. Опитайте да я отстраните, преди да продължите към стъпка 4.
Стъпка 4) Проверете линията Account obj[] = new Account[2];Той разпределя масив от две референтни променливи от тип Account, но не разпределя никакви Account предмети. И двата слота държат nullи обаждане obj[0].setData(...) на null препратката хвърля a NullPointerException по време на изпълнение.
Стъпка 5) Разкоментирайте редове 4 и 5. Тези два реда създават реални Account обекти и ги присвоете на obj[0] намлява obj[1]Масивът вече съдържа реални препратки и кодът работи чисто.
Изход:
For Array Element 0 Value of a = 1 Value of b = 2 For Array Element 1 Value of a = 3 Value of b = 4
Как да инициализираме масив от обекти в Java
Освен инициализацията, базирана на сетър, показана по-горе, масив от обекти може да бъде инициализиран по три по-ясни начина. Всеки стил жертва многословието за по-голяма яснота, така че изберете този, който най-добре отговаря на ситуацията.
- Инициализация на цикъла — разпределете масива, след което обходете всеки индекс и присвоете нов обект. Това е стандартният модел за големи масиви или когато броят на обектите е динамичен.
- Инициализация на конструктора — предавайте стойности директно на конструктора по време на създаването, така че не е необходимо отделно извикване на setter.
- Инициализация на литерали на масив — деклариране и попълване в едно единствено изречение с вграден код
{ ... }инициализатор, идеален за малки фиксирани множества.
class Account { int a, b; public Account(int a, int b) { // constructor this.a = a; this.b = b; } } public class InitDemo { public static void main(String[] args) { // 1) Loop initialisation Account[] loopArr = new Account[3]; for (int i = 0; i < loopArr.length; i++) { loopArr[i] = new Account(i, i * 10); } // 2) Constructor initialisation, one slot at a time Account[] ctorArr = new Account[2]; ctorArr[0] = new Account(1, 2); ctorArr[1] = new Account(3, 4); // 3) Array literal initialisation Account[] litArr = { new Account(5, 6), new Account(7, 8), new Account(9, 10) }; System.out.println("loop size = " + loopArr.length); System.out.println("ctor size = " + ctorArr.length); System.out.println("literal size= " + litArr.length); } }
Инициализацията на цикъла е най-безопасната по подразбиране, защото гарантира, че няма да има останал слот. nullИнициализацията на конструктора прави намерението изрично, когато всеки обект се нуждае от различни аргументи, а литералите на масивите поддържат малкия демо код компактен. Не смесвайте стилове в един и същ масив, освен ако нямате причина: последователността улеснява откриването на грешки.
Итериране и достъп до елементи в Java Масив от обекти
След като масив от обекти е попълнен, три модела покриват почти всяка нужда от достъп. Изберете стила на цикъла, който съответства на това колко контрол е необходим на кода върху индекса.
Classic for контур дава достъп до индекса, което е полезно за заместване на елементи, сравняване на съседи или итериране на поддиапазон.
for (int i = 0; i < obj.length; i++) { System.out.println("Element " + i); obj[i].showData(); }
Засилено for контур (цикълът „for-each“) скрива индекса и се чете по-естествено, когато индексът не е необходим:
for (Account acc : obj) {
acc.showData();
}
Потоци (Java 8 и по-късно) конвертирайте масива в конвейер, което е удобно за филтриране, mappingили агрегиране без писане на цикъл:
import java.util.Arrays;
Arrays.stream(obj)
.filter(acc -> acc.a > 0)
.forEach(Account::showData);
За да прочетете или актуализирате един елемент, използвайте директен достъп до индекс, например obj[1].setData(10, 20)Винаги първо проверявайте дължината с obj.length да избегна ArrayIndexOutOfBoundsExceptionКогато всеки слот може да бъде null, защитете достъпа с проверка за null или Optional за да поддържа програмата работеща, вместо да се срива.
Масив от обекти срещу ArrayList от обекти в Java
Обикновеният масив от обекти е бърз и предвидим, но фиксираният му размер се превръща в ограничение веднага щом броят на обектите се промени по време на изпълнение. JavaРамката за колекции предоставя ArrayList като динамична алтернатива. Таблицата по-долу показва кога всеки избор е подходящ.
| Особеност | Масив от обекти | ArrayList от обекти |
|---|---|---|
| Размер | Фиксирано при създаването | Расте и се свива автоматично |
| Декларация | Account[] a = new Account[5]; | List<Account> list = new ArrayList<>(); |
| Елемент за достъп | a[i] | list.get(i) |
| Добавяне на елемент | Не се поддържа след създаването | list.add(obj) |
| Безопасност на типа | Типизирано по време на компилация чрез декларация | Генеричните кодове се прилагат по време на компилация |
| Изпълнение | Малко по-бързо индексирано четене | Амортизирана O(1) добавка, някои режийни разходи на елемент |
| Предпочита се, когато | Размерът е известен и фиксиран | Размерът е неизвестен или се променя по време на изпълнение |
Използвайте масив, когато ограниченото използване на паметта и предвидимото индексиране са от значение, например в матрични оформления или критични за производителността „горещи пътища“. Потърсете ArrayList в повечето ежедневни кодове на приложения, защото възможността за добавяне и премахване без преразпределение надвишава малките разходи за всеки елемент.



