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.
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?
Reveal 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.
- 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
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.
- 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
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.
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.
- 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
Reading classlist[3].name
Given that classlist has been filled by the loop, what does the expression classlist[3].name do, step by step?
- 1Evaluate the array name
classlist names the array container, which holds references to Student objects in its slots.
- 2Apply 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.
- 3Apply the dot
The dot tells Java to read a property of that selected object, here the property name.
- 4Read the value
The result is the value of name stored inside the object at index 3, not inside the array.
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 likeStudent[] classlist = new Student[30]; then calling classlist[0].getAverage() immediately.
Why it failsThe statement allocates thirty slots, each set to null. No Student objects exist yet, so there is nothing to call the method on.
Do this insteadCreate 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 likeA loop that runs from i = 0 to i < 2 on an array of length 3, leaving classlist[2] as null.
Why it failsThe unfilled slot still holds null, so any later use of classlist[2].name fails at that line.
Do this insteadMake 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 likeWriting classlist[i].length when you meant the number of students.
Why it failsclasslist[i] selects one Student, and length belongs to the array as a whole, not to a single element.
Do this insteadUse 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 likeUsing 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 failsJava indices start at zero, so the slot labeled 3 is the fourth one.
Do this insteadRemember 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
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.lengthminus 1.