Arrays in Java
Declaring an array of objects uses the class name as the base type, such as Student[] classlist.
A Prediction Before the Explanation
Many learners who first meet arrays of objects expect one statement to do all the work. They assume that writing an array declaration and a creation statement will produce a set of ready-to-use objects. This article starts from that belief, because it is the most common way this topic goes wrong. Work through the question below before reading on.
What do you think happens?
After Student[] classlist = new Student[3]; how many Student objects now exist in memory?
Reveal answer
None: the array has three empty slots
Creating the array reserves the slots and sets each one to null. A null element exists as a slot but refers to nothing. Each Student object must be created separately, with new Student().
Declaring the Array and Creating Its Slots
An array in Java is created in two steps that are often written on one line. The declaration names the array and gives its element type. The creation uses the new keyword, the base type, and a size in square brackets to reserve the slots. For an array of objects, the base type is the class name, so Student[] classlist is a declaration of an array whose elements are Student values.
- Student[] names the element type and declares the variable classlist
- new Student[30] reserves 30 slots of type Student
- The statement creates the slots, not the Student objects
The size in the creation statement is fixed when the array is created. The array cannot grow or shrink afterward, so the size chosen must be large enough for the most data the program will store. The declaration and creation can also be written on one line, as Student[] classlist = new Student[30];, which is the form most programs use.
What Each Slot Holds Before Any Object Exists
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. Creating the array allocates the slots and sets each one to null, so the array has places ready for students but no student has been made yet.
This separation between the container and the objects it is meant to hold is the central idea of the topic. The array is a row of numbered places. The objects live separately, and each place gets a reference to one of them only when the program assigns one.
Filling Each Slot with a for Loop
To create the actual objects, the program must visit each index and assign a new object to it. A for loop does this. Its variable i takes the values 0 through 29 for a 30-slot 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 thirty nulls into thirty objects.
- The loop runs once for each index from 0 to 29
- new
Student()is the statement that creates an object - classlist[i] = stores the new object in the slot at index i
Finding the Failing Line
A program creates Student[] classlist = new Student[3]; and then, without filling the array, calls classlist[1].toString() to print the second student. Which statement fails, and why?
- 1Identify the slot
classlist[1] is the second slot. It was created by new Student[3], so it exists.
- 2Check what it holds
No loop assigned a new Student to it, so the slot still holds null, which refers to nothing.
- 3Locate the failure
The call classlist[1].toString() asks a Student object to do something. There is no object, so Java raises a
NullPointerExceptionat that call. The fault is the missing assignment, not the call itself. - 4Apply the fix
Run the fill loop, or assign classlist[1] = new
Student(), before using the slot.
The failure occurs at the call on classlist[1], because that slot is still null. The statement that should have prevented it is the missing new Student() assignment.
Reaching an Element Directly by Index
An array lets a program reach any element directly through its index. The expression classlist[2] does not search the array from the beginning. It computes the position of slot 2 from the start of the array and goes there. This is why the same access takes the same effort whether the array holds ten elements or ten thousand.
Java indices start at 0. The first element is classlist[0], and the last element of a 30-slot array is classlist[29]. An index is the distance from the start of the array, so the first slot has distance zero. Counting from 0 means the valid indices for an array of size n run from 0 to n minus 1, and an index outside that range is an error.
Tracking Filled Slots with a Counter
An array's size is fixed when it is created, so a program that may store fewer values than the size must track how many slots are in use. A counter variable, often named count, records how many slots are filled. The filled slots are indices 0 through count minus 1. The physical size of the array and the logical size of the data are two different things, and beginners often merge them.
- The array has 100 slots, but count says how many hold data
- The new value goes at index count, the next free slot
- count++ moves the boundary so the next value lands in the next slot
The loop that reads the data uses count rather than the array length to decide what is valid. Nothing is written past the end of the array, and the unused tail of the array never reaches the output. The first value goes into index 0, and after each store the counter advances, so each new value is placed into the next free slot.
Walking Backward from the Last Filled Index
A reverse loop starts at count minus 1 and decrements to 0, so it visits only the filled slots, last value first. The starting value is the only place where count is used, and it is the single line that keeps the unused tail of the array out of the output. The loop condition, index at least 0, is the stopping test for the front of the array.
int count = 3; // slots 0, 1, 2 hold data
for (int i = count - 1; i >= 0; i--) {
System.out.println(values[i]);
}- 1int i = count - 1 starts the loop at the last filled index, here 2
- 2i >= 0 is the stopping test, so the loop ends after index 0
- 3i-- moves the index one step toward the front of the array
- 4The body runs three times, printing values[2], values[1], then values[0]
Mistakes Beginners Make with Object Arrays
Common mistake Assuming the array creation statement creates the objects
What it looks likeStudent[] classlist = new Student[30]; followed directly by classlist[0].study();Why it failsThe creation statement reserves 30 slots and sets each one to null. It creates no Student objects.
Do this insteadCreate each object explicitly, for example with a for loop that assigns classlist[i] = new Student().
Common mistake Looping over slots that were never filled
What it looks likeCalling a method on classlist[i] when the loop that fills the array has not yet run for index i.
Why it failsAn unfilled slot holds null, which refers to nothing, so the call fails.
Do this insteadMake sure the fill statement runs before any use of the slot, or stop the loop at count minus 1.
Common mistake Reading past the filled data
What it looks likeStarting a printing loop at array.length minus 1 when only three of 100 slots hold values.
Why it failsThe unused tail of the array is not part of the data, so the output includes empty or meaningless values.
Do this insteadStart the reverse loop at count minus 1, where count tracks the filled slots.
Common mistake Starting indices at 1
What it looks likeWriting classlist[3] as the first element of a three-slot array.
Why it failsJava indices start at 0, so the valid indices for three slots are 0, 1, and 2.
Do this insteadUse classlist[0] for the first element and classlist[n minus 1] for the last.
Practice Tracing the Slots
A program runs Student[] classlist = new Student[4]; and then a loop that assigns a new Student to classlist[i] for i from 0 to 1 only. Which slots hold objects, which hold null, and what does the object count equal? Then say which statement fails if the program later calls classlist[3].study().
Hints
- Creating the array sets every slot to null first.
- The loop only touches indices 0 and 1.
- A call on a null slot fails at the call, not at the array creation.
Putting the Ideas Together
- 1Declaring Student[] classlist names an array whose elements are Student references; it creates no objects.
- 2new Student[30] allocates 30 slots, each starting as null, and each object must be created explicitly.
- 3A for loop with classlist[i] = new
Student()fills every slot with a real object, and an unfilled slot fails at the first use that dereferences it. - 4Indices start at 0, and a counter such as count marks the filled slots 0 through count minus 1, which a reverse loop can walk from last to first.
Key Takeaways
- Declaring an array of objects uses the class name as the base type, as in Student[] classlist, and does not create any objects.
- Creating the array with new Student[30] reserves 30 slots, each set to null, and the objects must be created separately.
- A loop that assigns classlist[i] = new
Student()fills the array, and an unfilled slot causes a failure when it is used. - A counter such as count tracks the filled slots, which are indices 0 through count minus 1, and a reverse loop can visit them last value first.