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

⚡ Умно обобщение

Масив от обекти в Java съхранява референции към обекти в съседен слот с фиксиран размер, позволявайки на една променлива да съхранява много екземпляри на клас и да осъществява достъп до всеки един чрез индекс за итерация, мутация и предаване на методи.

  • 📦 Съхранение на референтни данни: Всеки слот в Java масивът от обекти съдържа препратка към обект, а не към самия обект, подобно на всяка обектна променлива в Java.
  • 🧱 Създаване в две стъпки: Разпределете масива с new ClassName[size], след което разпределете всеки обект с new ClassName() преди да извикате методи върху него.
  • ⚠️ Изключение за NullPointer: Всеки слот започва като null. Извикването на метод на неинициализиран слот хвърля NullPointerException по време на изпълнение.
  • 🔁 Повторение: Използвайте for цикъл с дължина на масива или подобрен for цикъл, за да обходите всеки обект в масива.
  • 📏 Фиксиран размер: Масивът не може да расте след разпределението. Използвайте ArrayList, когато броят на обектите се променя по време на изпълнение.
  • 🏗️ Инициализация на конструктора: Конструкторите, подадени вградено по време на създаването, дават по-кратка и по-безопасна настройка, отколкото извикванията на setter след последваща обработка.
  • 🚚 Параметър на метода: Предаването на масива към метод прехвърля препратка, така че промените вътре в метода са видими за извикващия метод.

Масив от обекти в 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 по време на изпълнение.

Java Масив от обекти, референтни променливи

Стъпка 5) Разкоментирайте редове 4 и 5. Тези два реда създават реални Account обекти и ги присвоете на obj[0] намлява obj[1]Масивът вече съдържа реални препратки и кодът работи чисто.

Java Попълнен масив от обекти

Изход:

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

Освен инициализацията, базирана на сетър, показана по-горе, масив от обекти може да бъде инициализиран по три по-ясни начина. Всеки стил жертва многословието за по-голяма яснота, така че изберете този, който най-добре отговаря на ситуацията.

  1. Инициализация на цикъла — разпределете масива, след което обходете всеки индекс и присвоете нов обект. Това е стандартният модел за големи масиви или когато броят на обектите е динамичен.
  2. Инициализация на конструктора — предавайте стойности директно на конструктора по време на създаването, така че не е необходимо отделно извикване на setter.
  3. Инициализация на литерали на масив — деклариране и попълване в едно единствено изречение с вграден код { ... } инициализатор, идеален за малки фиксирани множества.
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 в повечето ежедневни кодове на приложения, защото възможността за добавяне и премахване без преразпределение надвишава малките разходи за всеки елемент.

Въпроси и Отговори

Масив от обекти в Java е контейнер с фиксиран размер, който съхранява препратки към екземпляри от един и същи клас. Всеки слот сочи към обект в heap-а, а достъпът до елементите се осъществява чрез индексиране, базирано на нула, с помощта на квадратни скоби.

Декларирайте масива с ClassName[] arr = new ClassName[size], след което създайте всеки обект с new ClassName() в цикъл или с вграден литерал на масив. И двете стъпки са задължителни; първата заделя само слотове за референции.

Защото new ClassName[size] само разпределя самия масив. Всеки слот започва като null, така че извикването на който и да е метод на този слот хвърля NullPointerException. Поправете го, като присвоите нов ClassName() на всеки индекс преди употреба.

Масивът има фиксиран размер, избран при създаването му, докато ArrayList се увеличава и свива автоматично. Масивите осигуряват малко по-бързо индексирано четене; ArrayList добавя удобни методи за добавяне, премахване и поточно предаване за ежедневен код на приложения.

Използвайте класически for цикъл с arr.length, когато ви е необходим индексът, или подобрен for-each цикъл за опростена итерация. За филтриране или трансформация, обвийте масива с Arrays.stream(arr) и свържете необходимия ви канал.

Декларирайте параметъра като ClassName[] име, след което извикайте метода с променливата масив. Java предава референцията към масива по стойност, така че мутациите в полетата на елементите вътре в метода са видими за извикващия.

Генераторите на код за машинно обучение разпознават двуетапния модел на разпределение и допълват липсващите нови редове ClassName(), които начинаещите забравят. Те също така предлагат ArrayList, когато размерът на целевата колекция е неизвестен, намалявайки грешките NullPointerException.

Да. GitHub Copilot генерира декларации на масиви, конструкторни цикли, итерационни блокове и ArrayList преобразувания от коментар, описващ домейн модела. RevПрегледайте генерирания код за правилни аргументи на конструктора и безопасна обработка на null стойности преди употреба.

Обобщете тази публикация с: