Concepts / Arrays in Java

Arrays in Java

Declaring an array of objects uses the class name as the base type, such as Student[] classlist.

  • Programming

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?

  • Three Student objects

  • One Student object

  • None: the array has three empty slots

Reveal answer
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.

java
Notes on the code
  • 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.

Student[]element type: Studentclasslistvariable namenewreserves spaceStudent[10]size 10 sets the slots
What each part of the declaration and creation statement contributes, and which part sets the size.

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.

classlist[0]nullStudent objects0 createdclasslist[1]nullclasslist[2]null
Each slot exists and is null. No Student object has been created, so the object count is zero.

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.

java
Notes on the code
  • 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
Worked example

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?

  1. 1
    Identify the slot

    classlist[1] is the second slot. It was created by new Student[3], so it exists.

  2. 2
    Check what it holds

    No loop assigned a new Student to it, so the slot still holds null, which refers to nothing.

  3. 3
    Locate the failure

    The call classlist[1].toString() asks a Student object to do something. There is no object, so Java raises a NullPointerException at that call. The fault is the missing assignment, not the call itself.

  4. 4
    Apply the fix

    Run the fill loop, or assign classlist[1] = new Student(), before using the slot.

Result

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.

classlist[0]Student objectclasslist[1]Student objectclasslist[2]Student objectclasslist[3]Student object
Each slot is reached directly by its index, and the first slot is index 0. The access to classlist[2] goes straight to the third slot.

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.

java
Notes on the code
  • 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.

Code walkthrough
int count = 3;   // slots 0, 1, 2 hold data

for (int i = count - 1; i >= 0; i--) {
    System.out.println(values[i]);
}
  1. 1
    int i = count - 1 starts the loop at the last filled index, here 2
  2. 2
    i >= 0 is the stopping test, so the loop ends after index 0
  3. 3
    i-- moves the index one step toward the front of the array
  4. 4
    The body runs three times, printing values[2], values[1], then values[0]
i = 2print values[2]i = 1print values[1]i = 0print values[0]i = -1loop stopsi--i--i--
The loop visits indices 2, 1, and 0 in that order, then stops when the index drops below 0. The unused slots beyond index 2 are never visited.

Mistakes Beginners Make with Object Arrays

  • Common mistake

    Assuming the array creation statement creates the objects

    What it looks like
    Student[] classlist = new Student[30]; followed directly by classlist[0].study();
    Why it fails

    The creation statement reserves 30 slots and sets each one to null. It creates no Student objects.

    Do this instead

    Create 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 like

    Calling a method on classlist[i] when the loop that fills the array has not yet run for index i.

    Why it fails

    An unfilled slot holds null, which refers to nothing, so the call fails.

    Do this instead

    Make 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 like

    Starting a printing loop at array.length minus 1 when only three of 100 slots hold values.

    Why it fails

    The unused tail of the array is not part of the data, so the output includes empty or meaningless values.

    Do this instead

    Start the reverse loop at count minus 1, where count tracks the filled slots.

  • Common mistake

    Starting indices at 1

    What it looks like

    Writing classlist[3] as the first element of a three-slot array.

    Why it fails

    Java indices start at 0, so the valid indices for three slots are 0, 1, and 2.

    Do this instead

    Use classlist[0] for the first element and classlist[n minus 1] for the last.

Practice Tracing the Slots

MEDIUM

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

  1. 1
    Declaring Student[] classlist names an array whose elements are Student references; it creates no objects.
  2. 2
    new Student[30] allocates 30 slots, each starting as null, and each object must be created explicitly.
  3. 3
    A 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.
  4. 4
    Indices 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.