Array Basics
Fixed-size, typed collections — your first data structure
After this lesson, you will be able to:
- Declare, allocate, and initialize arrays using both
newand curly-brace syntax - Access elements by index and use
.lengthto determine array size - Traverse arrays with standard
forloops and enhancedfor-eachloops - Explain why arrays are reference types and what aliasing means
- Apply array versions of the sum, max, min, and count patterns
The 100-Variable Problem
Suppose you need to store 100 test scores. You could declare 100 variables:
int score1 = 85;
int score2 = 92;
int score3 = 78;
// ... 97 more ...
That is absurd. You cannot loop over 100 separate variable names. You cannot pass them to a method without 100 parameters. And if the number of scores changes, you rewrite everything.
An array solves this: one variable holding multiple values of the same type, accessed by index:
int[] scores = new int[100];
scores[0] = 85; // first slot
scores[99] = 92; // last slot
One name, 100 slots. Now you can loop, pass to methods, and handle any size.
From CSCD 110: Python’s lists (
[1, 2, 3]) grow dynamically and can hold mixed types. Java arrays are fixed-size and hold only one type. You cannot append to a Java array — its size is set at creation. Java’sArrayList(covered later this week) is closer to Python lists.
Creating Arrays
Declaration and Allocation
// Two steps:
int[] scores; // declare (no memory yet)
scores = new int[5]; // allocate 5 slots on the heap
// Or one step:
int[] scores = new int[5]; // declare + allocate
Initialization with Values
int[] scores = {85, 92, 78, 95, 88};
This creates an array of size 5 with those exact values. The curly-brace syntax can only be used at declaration time.
Default Values
When you allocate with new, every slot gets a default:
| Type | Default |
|---|---|
int, long, short, byte |
0 |
double, float |
0.0 |
boolean |
false |
char |
'\0' (null character) |
String and other objects |
null |
int[] data = new int[3];
// data is [0, 0, 0] — not garbage, not undefined
Indexing and .length
Array indices start at 0 and go up to length - 1:
int[] scores = {85, 92, 78, 95, 88};
Index: [0] [1] [2] [3] [4]
Value: 85 92 78 95 88
scores.length = 5
scores[0] // 85 (first element)
scores[4] // 88 (last element)
scores[5] // ERROR: ArrayIndexOutOfBoundsException!
scores.length // 5
Common Pitfall:
.lengthis a property, not a method — no parentheses. Compare:array.length(no parens) vsstring.length()(with parens). The last valid index is alwaysarray.length - 1.
Given int[] arr = new int[10];, what is the last valid index?
Traversing Arrays
Standard For Loop
Use when you need the index:
int[] scores = {85, 92, 78, 95, 88};
for (int i = 0; i < scores.length; i++) {
System.out.println("Score " + i + ": " + scores[i]);
}
Enhanced For-Each Loop
Use when you only need the values:
for (int score : scores) {
System.out.println("Score: " + score);
}
Read as “for each score in scores.”
Key Insight: The for-each loop gives you a copy of each element. Modifying the loop variable does not modify the array:
for (int score : scores) { score = 100; // changes the COPY, not the array! } // scores is unchanged!Use the standard
forloop withscores[i] = 100when you need to modify elements.
Common Array Algorithms
These are the same patterns from Lesson 1.10, now applied to arrays.
Sum and Average
int sum = 0;
for (int score : scores) {
sum += score;
}
double average = (double) sum / scores.length;
Maximum and Minimum
int max = scores[0];
int min = scores[0];
for (int i = 1; i < scores.length; i++) {
if (scores[i] > max) { max = scores[i]; }
if (scores[i] < min) { min = scores[i]; }
}
Starting at scores[0] instead of Integer.MIN_VALUE is cleaner — you compare against an actual element.
Counting Matches
int count = 0;
for (int score : scores) {
if (score >= 90) {
count++;
}
}
System.out.println(count + " scores are A's");
Printing an Array
// DON'T print the array directly:
System.out.println(scores); // [I@6d06d69c (memory address!)
// DO use Arrays.toString():
import java.util.Arrays;
System.out.println(Arrays.toString(scores)); // [85, 92, 78, 95, 88]
Which loop type should you use to double every element in an array?
Arrays Are Reference Types
This is the most important concept in this lesson. Unlike int or double, an array variable does not hold the data directly — it holds a reference (a pointer) to the data on the heap.
int[] a = {1, 2, 3};
int[] b = a; // b points to the SAME array!
b[0] = 99;
System.out.println(a[0]); // 99 — a changed too!
Memory diagram:
Stack Heap
┌─────────┐ ┌───┬───┬───┐
│ a: ──────┼──────────►│99 │ 2 │ 3 │
├─────────┤ ┌────►└───┴───┴───┘
│ b: ──────┼──────┘
└─────────┘
Both a and b point to the same array object. This is called aliasing. Changing one changes the other.
This is fundamentally different from primitives:
int x = 5;
int y = x; // y gets a COPY of x's value
y = 99;
System.out.println(x); // still 5 — independent copy
Passing Arrays to Methods
When you pass an array to a method, you pass the reference. The method can modify the array’s contents, and the caller sees the changes:
public static void doubleAll(final int[] arr) {
for (int i = 0; i < arr.length; i++) {
arr[i] *= 2;
}
}
int[] data = {1, 2, 3};
doubleAll(data);
System.out.println(Arrays.toString(data)); // [2, 4, 6]
Key Insight: Primitives are passed by value (the method gets a copy). Arrays are also technically passed by value — but the “value” is the reference. So the method gets a copy of the pointer, which still points to the same array. The method cannot reassign the caller’s variable, but it can modify the array’s contents.
Copying an Array
To make an independent copy:
int[] original = {1, 2, 3};
// Manual copy:
int[] copy = new int[original.length];
for (int i = 0; i < original.length; i++) {
copy[i] = original[i];
}
// Or use Arrays.copyOf():
int[] copy = Arrays.copyOf(original, original.length);
Now copy is independent — changing one does not affect the other.
What does this code print?
int[] a = {10, 20, 30};
int[] b = a;
b[1] = 99;
System.out.println(a[1]);
int[] a = {1, 2, 3};
int[] b = a;
b[0] = 99;
System.out.println(a[0]);
Complete Example: Grade Report
import java.util.Arrays;
import java.util.Scanner;
public class GradeReport {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("How many students? ");
int n = scanner.nextInt();
int[] scores = new int[n];
for (int i = 0; i < scores.length; i++) {
System.out.print("Score " + (i + 1) + ": ");
scores[i] = scanner.nextInt();
}
// Compute statistics
int sum = 0;
int max = scores[0];
int min = scores[0];
int countA = 0;
for (int i = 0; i < scores.length; i++) {
sum += scores[i];
if (scores[i] > max) { max = scores[i]; }
if (scores[i] < min) { min = scores[i]; }
if (scores[i] >= 90) { countA++; }
}
double average = (double) sum / scores.length;
System.out.println("\n--- Grade Report ---");
System.out.println("Scores: " + Arrays.toString(scores));
System.out.printf("Average: %.1f%n", average);
System.out.println("Highest: " + max);
System.out.println("Lowest: " + min);
System.out.println("A grades: " + countA + " of " + scores.length);
}
}
Sample run:
How many students? 5
Score 1: 85
Score 2: 92
Score 3: 78
Score 4: 95
Score 5: 88
--- Grade Report ---
Scores: [85, 92, 78, 95, 88]
Average: 87.6
Highest: 95
Lowest: 78
A grades: 2 of 5
Quick Reference
| Operation | Code |
|---|---|
| Declare & allocate | int[] arr = new int[size]; |
| Declare & initialize | int[] arr = {1, 2, 3}; |
| Access element | arr[index] |
| Array size | arr.length (no parentheses) |
| Traverse with index | for (int i = 0; i < arr.length; i++) |
| Traverse values only | for (int x : arr) |
| Print array | Arrays.toString(arr) |
| Copy array | Arrays.copyOf(arr, arr.length) |
Summary
Arrays store multiple values of the same type in a single variable, accessed by zero-based index. The size is fixed at creation and accessed via .length (no parentheses). Default values are 0, 0.0, false, or null depending on the type.
The standard for loop gives you index access (needed for modification). The for-each loop is cleaner for read-only traversal but gives you copies, not references to elements.
Arrays are reference types. Assigning one array variable to another creates an alias — both point to the same data. Passing an array to a method passes the reference, so the method can modify the original. Use Arrays.copyOf() for independent copies.
Next lesson: Searching arrays — linear search, binary search, and when to use each.