Concepts / Arrays of Objects

Arrays of Objects

Once an array of objects is filled, classlist[i] refers to a Student object, and it can be used anywhere a Student variable could be used.

  • Programming

Why a Class Roster Needs an Array of Objects

Suppose a teacher keeps track of a class of students, and each student is represented by a Student object. Storing those objects in an array lets a program hold the whole class under one name. The harder question is how to reach one particular student once they are sitting inside that array. This article follows a single array, called classlist, and shows exactly what happens when you ask it for one of its students, what you can ask that student to do, and where learners most often go wrong.

What do you think happens?

Given Student[] classlist = new Student[3]; and nothing else, what do you think classlist[0].name evaluates to?

  • The name of the first student, which is an empty string

  • A Student object with default values

  • Nothing usable yet: classlist[0] refers to no object, so using it fails

Reveal answer
Answer:

Nothing usable yet: classlist[0] refers to no object, so using it fails.

The declaration and creation statement only set up thirty-style empty slots, each holding null. Java does not create any Student objects here, so the expression classlist[0].name tries to use a null reference and fails at runtime. Keep this in mind as you read the rest of the article: the rest of the topic is about why that failure happens and how to prevent it.

Many learners who first meet arrays of objects assume that one statement does all the work. They expect that writing an array declaration and a creation statement will produce a set of ready-to-use objects. This is the most common way this topic goes wrong, so the sections that follow are built to test that belief directly.

What Exists After the Array Is Created

An array's base type can be a class, not only a primitive type such as int or a type such as String. When the base type is Student, every element of the array is a variable whose type is Student. A variable of that type is a place that can hold a reference to a Student object. It is not the object itself.

java
Notes on the code
  • Student[] sets the element type: every slot will hold a reference to a Student
  • new Student[3] sets the length: three slots are allocated
  • classlist is the name of the array container
classlist[0]nullclasslist[1]nullclasslist[2]null
After Student[] classlist = new Student[3]; runs, which slots hold anything yet, and do any Student objects exist?

Creating the array allocates the slots and sets each slot to null. A null element means the slot exists but refers to nothing. The array has three places ready for students, but no student has been made yet. In the source's example, new Student[30] allocates thirty elements, each starting as null. This separation between the container and the objects it is meant to hold is the central idea of the whole topic.

Filling Each Slot With a Student

To create the actual objects, the program must visit each index and assign a new object to it. A for loop does this. The loop variable i takes the values 0 through 2 in this small array, and on each pass the statement creates one Student and stores it in the slot at that index. The loop is the part that turns three nulls into three objects.

java
Notes on the code
  • Line 1 allocates three null slots; it creates no Student objects
  • The loop variable i starts at 0, the first valid index in Java
  • Each pass runs classlist[i] = new Student(), which fills exactly one slot
  • The loop stops before i reaches 3, so the last filled index is 2
i = 0classlist[0] = newStudent()i = 1classlist[1] = newStudent()i = 2classlist[2] = newStudent()next passnext pass
As the loop runs, which element is filled on each pass, and what does the loop leave behind after the last pass?

Trace the loop by hand before running it. On the first pass, the slot at index 0 receives a new Student. On the second pass, index 1 receives one. On the third pass, index 2 receives one, and then the condition fails because i has reached the array length. Every slot is now filled, and every element is a real object rather than null.

Reaching One Student Through the Index

Once every slot has been filled with a Student object, the expression classlist[i] stands for the Student that lives at position i. From that point on, you can treat classlist[i] the same way you would treat any variable declared as type Student. The brackets select the slot; the slot leads you to the object.

classlist[0]Student objectclasslist[1]Student objectclasslist[2]Student objectclasslist[3]Student object, fourth slot
When I write classlist[3], what does that expression point to, and how does the index connect to one stored object?

Read the diagram from left to right. Each box is one slot of the array, labeled with its index, and each slot holds a Student object. The highlighted box is classlist[3]. Java indices count from zero, so the box labeled 3 is the fourth slot. The source describes this same slot as student number 3, which is the everyday way of speaking, while the index used in code is the position counted from zero.

Properties and methods are reached in the same way. A property belongs to the object, not to the array, so the pattern is always the array name, then the index in brackets, then a dot and the name. The source gives classlist[i].name for the name of the ith Student. For methods, you select the object with the index, use the dot to name the method, and add parentheses for the call. The source gives classlist[i].getAverage() to compute the average for student number i.

java
Notes on the code
  • classlist[0].name reads a property of the object at index 0
  • classlist[2].getAverage() runs the method on the object at index 2 and uses that object's own data
  • classlist[3].name = "Maya" writes a property of the object at index 3

The method call deserves a closer look. Because the index picks out an object, getAverage() runs on that object and uses its own data. Calling it on classlist[2] and on classlist[4] therefore usually gives different results, because each Student carries different data. The array is only a way of naming the object. Once the index has selected it, the object behaves as it always does, and you can pass it to other code just as you would any Student variable.

Tracing Access Through a Worked Case

Worked example

Reading classlist[3].name

Given that classlist has been filled by the loop, what does the expression classlist[3].name do, step by step?

  1. 1
    Evaluate the array name

    classlist names the array container, which holds references to Student objects in its slots.

  2. 2
    Apply the index

    The index 3 selects the slot counted from zero, which is the fourth slot. The slot leads to the Student object stored there.

  3. 3
    Apply the dot

    The dot tells Java to read a property of that selected object, here the property name.

  4. 4
    Read the value

    The result is the value of name stored inside the object at index 3, not inside the array.

Result

The expression produces the name of the Student stored at index 3. If that slot had never been filled, this same expression would fail, because it would try to read a property of null.

The same reasoning applies to the declaration-only case from the opening. Java cannot read a property from an object that was never created. In a filled array, classlist[i] refers to an object. In an array that was only declared and allocated, classlist[i] refers to null, and the attempt to use it is the failure point.

Mistakes Beginners Make With Object Arrays

Almost all of these errors come from forgetting that the array creation statement stops at null. Each one is easier to spot once you know which line should have created the object.

  • Common mistake

    Believing that new Student[30] creates thirty students

    What it looks like

    Student[] classlist = new Student[30]; then calling classlist[0].getAverage() immediately.

    Why it fails

    The statement allocates thirty slots, each set to null. No Student objects exist yet, so there is nothing to call the method on.

    Do this instead

    Create each object explicitly, for example with a loop that runs classlist[i] = new Student() for each index.

  • Common mistake

    Skipping the loop or filling only some slots

    What it looks like

    A loop that runs from i = 0 to i < 2 on an array of length 3, leaving classlist[2] as null.

    Why it fails

    The unfilled slot still holds null, so any later use of classlist[2].name fails at that line.

    Do this instead

    Make the loop condition use classlist.length so every index from 0 through length minus 1 is visited.

  • Common mistake

    Treating classlist[i] as the array instead of an object

    What it looks like

    Writing classlist[i].length when you meant the number of students.

    Why it fails

    classlist[i] selects one Student, and length belongs to the array as a whole, not to a single element.

    Do this instead

    Use classlist.length for the number of slots, and classlist[i].name or classlist[i].getAverage() for properties and methods of one student.

  • Common mistake

    Counting the index from one

    What it looks like

    Using classlist[3] to mean the third student, when the source calls that position student number 3 but the index is the fourth slot.

    Why it fails

    Java indices start at zero, so the slot labeled 3 is the fourth one.

    Do this instead

    Remember that the last valid index is length minus 1, and keep the everyday student number separate from the code index.

Practice Filling and Reading an Object Array

MEDIUM

Declare an array named roster that holds four Student objects, fill every slot with a new Student using a loop, and then write one statement that calls getAverage() on the object at index 2. Before you run anything, state which line would fail if you removed the loop and kept the same method call.

Hints
  • Use Student[] roster = new Student[4]; to declare and allocate the slots.
  • The loop should run while i is less than roster.length.
  • Removing the loop leaves every slot null, so the method call on roster[2] is the failing line.

Key Takeaways

  • Declaring Student[] classlist = new Student[n] creates n null slots; it does not create any Student objects, and each object must be created explicitly.
  • A loop that runs classlist[i] = new Student() for each index fills every slot, and an unfilled slot causes a failure at the first line that uses it as an object.
  • Once filled, classlist[i] refers to a Student and can be used anywhere a Student variable could be used.
  • Properties use classlist[i].name and methods use classlist[i].getAverage(); both select the object by index first, then apply the dot.
  • Java indices count from zero, so the last valid index is classlist.length minus 1.