Skip to content
Java arrays 6 min read

Array of Objects

An array of objects lets you store multiple instances of a class in a single, indexed container. It bridges two of Java’s most fundamental concepts — arrays and classes & objects — and is the starting point for understanding how real-world data collections work.

Why Store Objects in an Array?

Imagine you’re writing a student management system. Without object arrays you’d need separate variables for every student’s name, grade, and ID. With an array of objects, you store each Student instance neatly in one place and loop over all of them in a few lines.

Student[] roster = new Student[30]; // 30 Student slots

That’s the core idea. The array itself holds references to objects, not the objects directly.

Declaring and Creating an Object Array

Creating an array of objects is a two-step process:

  1. Declare and allocate the array (this creates null references by default).
  2. Create each object and assign it to a slot.
class Student {
    String name;
    int grade;

    Student(String name, int grade) {
        this.name  = name;
        this.grade = grade;
    }
}

public class Main {
    public static void main(String[] args) {
        // Step 1 — allocate array of 3 Student references
        Student[] students = new Student[3];

        // Step 2 — create each object and assign
        students[0] = new Student("Alice", 90);
        students[1] = new Student("Bob",   85);
        students[2] = new Student("Carol", 92);

        // Access a field on the first object
        System.out.println(students[0].name + " scored " + students[0].grade);
    }
}

Output:

Alice scored 90

Warning: After new Student[3], every slot contains null. Calling any method on an uninitialized slot throws a NullPointerException. Always initialize before use.

Inline Initialization with an Array Initializer

If you know all your objects up front, you can declare and populate in one shot using an array initializer:

Student[] students = {
    new Student("Alice", 90),
    new Student("Bob",   85),
    new Student("Carol", 92)
};

This is identical to the two-step approach — Java still allocates the array and assigns each reference — but the syntax is more concise.

Iterating Over an Object Array

Using a Traditional for Loop

for (int i = 0; i < students.length; i++) {
    System.out.println(i + ": " + students[i].name + " — " + students[i].grade);
}

Output:

0: Alice — 90
1: Bob — 85
2: Carol — 92

Using the Enhanced for-each Loop

The for-each loop is cleaner when you don’t need the index:

for (Student s : students) {
    System.out.println(s.name + " scored " + s.grade);
}

Output:

Alice scored 90
Bob scored 85
Carol scored 92

Tip: Prefer the for-each loop for read-only iteration. Use the indexed for loop when you need the position or want to modify elements.

Adding Methods to Your Class

Object arrays become far more useful when your class encapsulates behavior. Add a toString() method so printing is easy:

class Student {
    String name;
    int grade;

    Student(String name, int grade) {
        this.name  = name;
        this.grade = grade;
    }

    @Override
    public String toString() {
        return name + " (grade: " + grade + ")";
    }

    boolean isPassing() {
        return grade >= 60;
    }
}

public class Main {
    public static void main(String[] args) {
        Student[] students = {
            new Student("Alice", 90),
            new Student("Bob",   55),
            new Student("Carol", 72)
        };

        for (Student s : students) {
            String status = s.isPassing() ? "PASS" : "FAIL";
            System.out.println(s + " -> " + status);
        }
    }
}

Output:

Alice (grade: 90) -> PASS
Bob (grade: 55) -> FAIL
Carol (grade: 72) -> PASS

Note: Overriding toString() is a best practice for any class whose instances you’ll print or log. Java calls toString() automatically when you pass an object to System.out.println.

Searching an Object Array

A simple linear search compares a field value across all elements:

public class Main {
    static Student findByName(Student[] arr, String name) {
        for (Student s : arr) {
            if (s.name.equals(name)) {
                return s;
            }
        }
        return null; // not found
    }

    public static void main(String[] args) {
        Student[] students = {
            new Student("Alice", 90),
            new Student("Bob",   85),
            new Student("Carol", 92)
        };

        Student found = findByName(students, "Bob");
        if (found != null) {
            System.out.println("Found: " + found);
        }
    }
}

Output:

Found: Bob (grade: 85)

Tip: Use String.equals() — not == — when comparing string fields. == checks reference identity, not character content. See String Comparison for details.

Sorting an Object Array

You can sort an object array with Arrays.sort() once your class implements Comparable, or by passing a Comparator:

import java.util.Arrays;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {
        Student[] students = {
            new Student("Carol", 92),
            new Student("Alice", 90),
            new Student("Bob",   85)
        };

        // Sort by grade descending
        Arrays.sort(students, Comparator.comparingInt((Student s) -> s.grade).reversed());

        for (Student s : students) {
            System.out.println(s);
        }
    }
}

Output:

Carol (grade: 92)
Alice (grade: 90)
Bob (grade: 85)

See Arrays Utility Class for more on Arrays.sort() and other helpers.

Under the Hood

Understanding what Java does in memory helps you avoid subtle bugs.

The Heap Split

When you write Student[] students = new Student[3], Java allocates one array object on the heap. This array stores three references (each 4 or 8 bytes depending on JVM pointer compression), all initialized to null. No Student objects exist yet.

When you write students[0] = new Student("Alice", 90), a separate Student object is created elsewhere on the heap, and its address is stored in students[0].

Stack:          Heap (array):            Heap (objects):
students -----> [ ref0 | ref1 | ref2 ]
                    |       |       |
                    v       v       v
                 Student  Student  Student
                 "Alice"  "Bob"   "Carol"

This indirection has two important consequences:

  • Assignment copies the reference, not the object. students[1] = students[0] makes both slots point to the same Student. Changing students[1].grade also changes students[0].grade.
  • Garbage collection only reclaims a Student object when no references remain. Setting a slot to null (students[0] = null) removes that reference; the object is eligible for GC if nothing else holds it.

Type Safety via the JVM

The JVM knows the element type of every array at runtime (this is called a reifiable type). If you try to store the wrong object type, you get an ArrayStoreException at runtime, not just a compile error. This is different from generics, which are erased at compile time.

Object[] arr = new Student[3];
arr[0] = new Student("Alice", 90); // OK
arr[1] = "oops";                   // ArrayStoreException at runtime!

Performance Notes

  • Random access (students[i]) is O(1) — the JVM calculates the slot address as base + i * referenceSize.
  • Iteration is cache-friendly for the array itself (the references are contiguous), but the actual objects can be scattered across the heap, which can reduce CPU cache efficiency for very large arrays.
  • For mutable, resizable collections of objects, prefer ArrayList, which wraps an object array internally and grows it automatically.

Common Pitfalls

MistakeWhat Goes WrongFix
Forgetting to initialize each slotNullPointerExceptionUse a loop or inline initializer to create every object
Using == to compare field stringsCompares addresses, not contentUse .equals()
Copying a slot without cloningBoth references point to one objectImplement a copy constructor or use Object Cloning
Accessing out-of-bounds indexArrayIndexOutOfBoundsExceptionAlways check index against array.length
  • Arrays — foundational array concepts every Java programmer needs
  • Classes & Objects — how to define the class you’ll store in your array
  • Constructors — how object initialization inside the array works
  • ArrayList — the flexible, resizable alternative to a fixed object array
  • Comparable — make your objects naturally sortable inside an array
  • Arrays Utility Class — sort, search, and fill object arrays with one-liners
Last updated June 13, 2026
Was this helpful?