Java Full Course: Mastering the Language Arrays in Java

Arrays in Java

(Complete Notes | Beginner to Advanced | Professional & Exam-Oriented | Masterclass)

1. Introduction to Arrays

An array is a fixed size, indexed collection of elements of the same type. It allows you to store and manage multiple values under a single variable name.

Arrays in Java are classified into two broad categories:

  1. Single dimensional arrays – a linear sequence of elements (e.g., an array of integers).
  2. Multi dimensional arrays – arrays whose elements are themselves arrays. These can be:
    • Rectangular arrays – each row has the same number of columns.
    • Jagged arrays – rows can have different lengths.

All arrays are objects in Java, have a length property, and use zero based indexing. They provide efficient direct access but have a fixed size after creation.

In the following sections, we will cover declaration, creation, initialization, element access, multi dimensional arrays, and common utility methods.


2. Single Dimensional Arrays (One Dimensional Arrays)

A single dimensional array is a container that holds a fixed number of values of a single type. The values are stored in contiguous memory locations, and each element can be accessed directly using an integer index. Arrays are objects in Java, which means they have methods (like clone()) and a public field length.


2.1 Declaring an Array

Declaration does not allocate memory; it simply tells the compiler that a variable will refer to an array of a given type.

int[] numbers; // preferred style int numbers[]; // alternative C style
  • The first form (int[] numbers) is preferred because it clearly indicates that numbers is an array of int.
  • You can declare multiple arrays in one line:
int[] arr1, arr2; // both are int arrays int arr3[], arr4; // arr3 is an int array, arr4 is an int variable

The second form can be confusing; the first style avoids this pitfall.

  • At declaration, no array is created; numbers is a reference variable that can later point to an array object.

2.2 Creating an Array (Instantiation)

To create an array, you use the new keyword followed by the type and the size in square brackets. The size can be a literal, a variable, or an expression, but it must be a non negative int.

numbers = new int[5]; // creates an array of 5 ints
  • The array size is fixed at creation and cannot change later.
  • If the size is given by a variable, it is evaluated at runtime:
int size = 10; double[] data = new double[size];

Memory behavior: The new operator allocates memory on the heap for the array object. All elements are initialized to their default values (see §2.4).

You can combine declaration and creation:

int[] numbers = new int[5];

If the size is zero, the array is empty (no elements), but it is a valid object:

int[] empty = new int[0]; System.out.println(empty.length); // 0

2.3 Initializing an Array

Arrays can be initialized in several ways.

a) Using an Array Initializer (Inline)

int[] numbers = {10, 20, 30, 40, 50};
  • The size is inferred from the number of elements.
  • This form can only be used at declaration. It is equivalent to:
int[] numbers = new int[]{10, 20, 30, 40, 50};

b) Using new with an Array Initializer

int[] numbers = new int[]{10, 20, 30, 40, 50};
  • This syntax can be used anywhere, e.g., to re assign an existing array variable:
numbers = new int[]{60, 70, 80};

c) Assigning Values Individually

After creation, you can assign each element:

int[] numbers = new int[5]; numbers[0] = 10; numbers[1] = 20; numbers[2] = 30; numbers[3] = 40; numbers[4] = 50;
  • If you don't assign a value, the element retains its default value.

d) Using a Loop

for (int i = 0; i < numbers.length; i++) { numbers[i] = i * 10; }

2.4 Default Values

When an array is created with new, all elements are automatically set to the default value for that type. This is guaranteed by the Java language.

Element TypeDefault Value
byte, short, int, long0
float, double0.0 (or 0.0f for float)
char'\u0000' (null character)
booleanfalse
Object referencenull

Example:

int[] intArr = new int[3]; System.out.println(intArr[0]); // 0 String[] strArr = new String[3]; System.out.println(strArr[0]); // null

This default initialization happens only when the array is created with new. If you use an array initializer, you provide explicit values.


2.5 Accessing Elements

You access an element by placing its index inside square brackets after the array variable name. Indices are zero based – the first element is at index 0, the last at array.length - 1.

int[] numbers = {10, 20, 30}; System.out.println(numbers[0]); // 10 numbers[1] = 25; // change the second element

Bounds checking: Java performs runtime bounds checking. If you attempt to access an index less than 0 or greater than or equal to array.length, an ArrayIndexOutOfBoundsException is thrown.

int[] arr = new int[5]; arr[5] = 10; // Exception: Index 5 out of bounds for length 5

Performance: Bounds checking adds a small overhead, but it ensures safety and prevents memory corruption.


2.6 The length Property

Every array object has a public, final field called length that holds the number of elements. It is not a method; you do not use parentheses.

int[] numbers = new int[10]; System.out.println(numbers.length); // 10
  • length is final; you cannot assign a new value to it.
  • It is often used in loops to control iteration.

2.7 Iterating Over an Array

a) Traditional for Loop

for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); }
  • You have access to the index, which can be used for calculations or when you need to modify elements.

b) Enhanced for Loop (for-each)

for (int value : numbers) { System.out.println(value); }
  • The variable value receives a copy of each element. For primitive arrays, modifying value does not affect the array. For arrays of objects, you can modify the object's state (since the reference is copied, not the object), but you cannot replace the object itself.

c) Using Arrays.toString()

import java.util.Arrays; System.out.println(Arrays.toString(numbers)); // Output: [10, 20, 30, 40, 50]
  • This is convenient for debugging; it returns a string representation of the array.

d) Using Streams (Java 8+)

Arrays.stream(numbers).forEach(System.out::println);

2.8 Copying Arrays

Because arrays are objects, assignment does not copy the array; it copies the reference.

int[] original = {1, 2, 3}; int[] copy = original; // both refer to the same array copy[0] = 99; System.out.println(original[0]); // 99 (original changed)

To create a separate copy, use one of the following methods.

a) Manual Loop

int[] copy = new int[original.length]; for (int i = 0; i < original.length; i++) { copy[i] = original[i]; }

b) System.arraycopy()

System.arraycopy(original, 0, copy, 0, original.length);
  • Parameters: source array, source start index, destination array, destination start index, number of elements.
  • It is a native method and very efficient.

c) Arrays.copyOf()

int[] copy = Arrays.copyOf(original, original.length);
  • Creates a new array, copies the specified number of elements. If the new length is larger, the extra elements are filled with default values.

d) clone()

int[] copy = original.clone();
  • For arrays, clone() returns a shallow copy.
Crucial

[!IMPORTANT] Shallow copy note: For arrays of reference types, all these methods copy the references, not the objects themselves. So changes to the objects themselves (not the array references) will be visible in both arrays.


2.9 Command Line Arguments (main Method)

The main method receives an array of String objects – the command line arguments passed when the program is executed.

public static void main(String[] args) { System.out.println("Number of arguments: " + args.length); for (int i = 0; i < args.length; i++) { System.out.println("args[" + i + "] = " + args[i]); } }

If no arguments are provided, args.length is 0 (not null).


2.10 Common Operations on Arrays

a) Sum and Average

int sum = 0; for (int num : numbers) { sum += num; } double average = (double) sum / numbers.length;

b) Finding Maximum/Minimum

int max = numbers[0]; for (int i = 1; i < numbers.length; i++) { if (numbers[i] > max) { max = numbers[i]; } }

c) Linear Search

int target = 25; int index = -1; for (int i = 0; i < numbers.length; i++) { if (numbers[i] == target) { index = i; break; } }

d) Reversing an Array

for (int i = 0; i < numbers.length / 2; i++) { int temp = numbers[i]; numbers[i] = numbers[numbers.length - 1 - i]; numbers[numbers.length - 1 - i] = temp; }

e) Sorting (Using Arrays.sort())

Arrays.sort(numbers);
  • Sorts the array in ascending order using a dual pivot Quicksort (for primitives) or Timsort (for objects).
  • For descending order, you can sort and then reverse, or use Comparator with wrapper types.

2.11 Arrays of Objects

Arrays can store references to objects.

String[] names = new String[3]; // all elements are null names[0] = "Alice"; names[1] = "Bob"; names[2] = "Charlie";
Warning

[!WARNING] Creating the array does not create the objects; it only allocates space for references. You must instantiate each object separately.

Point[] points = new Point[5]; for (int i = 0; i < points.length; i++) { points[i] = new Point(i, i); }

If you forget to create the objects, accessing an element results in a NullPointerException.


2.12 Common Pitfalls and How to Avoid Them

PitfallExampleSolution
Off by one errorfor (int i = 0; i <= arr.length; i++)Use < arr.length
Using length() instead of lengtharr.length() (compiles only if arr is a String)Arrays use length (field), String uses length() (method)
Null array referenceint[] arr = null; arr[0] = 5; → NullPointerExceptionAlways initialize arrays before use
Index out of boundsarr[arr.length]Last index is length - 1
Confusing declarationint[] a, b; (both arrays) vs int a[], b; (a is array, b is int)Use the type[] var style to avoid confusion
Modifying array while iterating with enhanced forfor (int x : arr) { x = 5; } does not modify arrayUse traditional loop for modifications
Using == to compare arraysif (arr1 == arr2) checks reference equality, not contentUse Arrays.equals(arr1, arr2)

2.13 Best Practices

  • Use Arrays utility methodssort(), binarySearch(), fill(), equals(), copyOf() – they are well tested and efficient.
  • Prefer the enhanced for loop when you only need to read elements.
  • Validate indices before accessing, especially when the index comes from user input or external sources.
  • Consider using ArrayList if you need a dynamically resizable collection. Arrays are best when the size is fixed and known in advance.
  • Use length field consistently; do not hard code sizes.
  • Document the meaning of the array – what each index represents (e.g., grades[0] is the first quiz score).
  • Initialize arrays immediately when possible, either with default values or with meaningful data.

2.14 Complete Example

import java.util.Arrays; public class ArrayDemo { public static void main(String[] args) { // Declaration, creation, initialization int[] numbers = new int[5]; for (int i = 0; i < numbers.length; i++) { numbers[i] = (i + 1) * 10; // 10, 20, 30, 40, 50 } // Display using toString System.out.println("Original: " + Arrays.toString(numbers)); // Sum and average int sum = 0; for (int num : numbers) sum += num; System.out.println("Sum: " + sum); System.out.println("Average: " + (sum / (double) numbers.length)); // Find max int max = numbers[0]; for (int i = 1; i < numbers.length; i++) { if (numbers[i] > max) max = numbers[i]; } System.out.println("Max: " + max); // Reverse for (int i = 0; i < numbers.length / 2; i++) { int temp = numbers[i]; numbers[i] = numbers[numbers.length - 1 - i]; numbers[numbers.length - 1 - i] = temp; } System.out.println("Reversed: " + Arrays.toString(numbers)); // Sort Arrays.sort(numbers); System.out.println("Sorted: " + Arrays.toString(numbers)); // Copy int[] copy = Arrays.copyOf(numbers, numbers.length); System.out.println("Copy: " + Arrays.toString(copy)); // Equality System.out.println("Equal: " + Arrays.equals(numbers, copy)); // Fill int[] filled = new int[5]; Arrays.fill(filled, 7); System.out.println("Filled: " + Arrays.toString(filled)); } }

2.15 Key Points to Remember

  • Arrays are objects that hold a fixed number of elements of a single type.
  • Declaration does not allocate memory; creation with new does.
  • Array indices start at 0 and end at length - 1.
  • Accessing an invalid index throws ArrayIndexOutOfBoundsException.
  • The length field gives the number of elements (not a method).
  • Arrays are automatically initialized with default values when created with new.
  • You can copy arrays using loops, System.arraycopy(), Arrays.copyOf(), or clone().
  • Use the enhanced for loop for reading, but it cannot modify the array contents.
  • For dynamic sizing, consider ArrayList.
  • The Arrays utility class provides many convenient methods.

3. Multi Dimensional Arrays

A multi dimensional array in Java is an array whose elements are themselves arrays. The most common multi dimensional array is the two dimensional array (like a matrix), but Java supports arrays of any number of dimensions (3D, 4D, etc.). Multi dimensional arrays are not stored as a contiguous block of all elements; instead, they are implemented as arrays of arrays. This gives flexibility, including the ability to create jagged arrays (rows of different lengths).


3.1 Declaring Multi Dimensional Arrays

You declare a multi dimensional array by adding multiple pairs of square brackets.

int[][] matrix; // 2D array (preferred style) int[] matrix[]; // also valid int matrix[][]; // also valid

For three dimensions:

int[][][] cube;
  • The brackets can be placed with the type or with the variable name, but the type[][] var style is most readable.

3.2 Creating Multi Dimensional Arrays

Creating a multi dimensional array involves allocating memory for each dimension.

a) Creating a Rectangular 2D Array

int[][] matrix = new int[3][4]; // 3 rows, 4 columns
  • This creates an array of 3 elements, each of which is an int[] of length 4.
  • All elements are initialized to the default value for int (0).

b) Creating a 3D Array

int[][][] cube = new int[3][4][5]; // 3 x 4 x 5

c) Creating Jagged Arrays (Rows with Different Lengths)

You can allocate the second dimension separately:

int[][] jagged = new int[3][]; // allocate only the first dimension jagged[0] = new int[2]; // row 0 has 2 columns jagged[1] = new int[5]; // row 1 has 5 columns jagged[2] = new int[3]; // row 2 has 3 columns
  • This is called a jagged array because the rows can have varying lengths.
  • Each row is a separate array object.

3.3 Initializing Multi Dimensional Arrays

a) Using an Array Initializer

int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
  • This creates a 3×3 rectangular array.
  • You can also create a jagged array with an initializer:
int[][] jagged = { {1, 2}, {3, 4, 5, 6}, {7, 8, 9} };

b) Using Nested Loops

int[][] matrix = new int[3][4]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { matrix[i][j] = i * 10 + j; } }

c) Individual Element Assignment

int[][] matrix = new int[2][2]; matrix[0][0] = 5; matrix[0][1] = 10; matrix[1][0] = 15; matrix[1][1] = 20;

3.4 Accessing Elements

Use the appropriate number of indices.

int[][] matrix = {{1, 2}, {3, 4}}; System.out.println(matrix[0][1]); // 2 matrix[1][0] = 99;

For a 3D array:

int[][][] cube = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}; int value = cube[1][0][1]; // 6
Crucial

[!IMPORTANT] Bounds Checking: Each index must be within the respective dimension's length; otherwise, ArrayIndexOutOfBoundsException is thrown.


3.5 The length Property

For multi dimensional arrays, length gives the number of elements in the first dimension (rows). Each inner array also has its own length.

int[][] matrix = new int[3][4]; System.out.println(matrix.length); // 3 (number of rows) System.out.println(matrix[0].length); // 4 (number of columns in row 0)

For jagged arrays:

int[][] jagged = new int[3][]; jagged[0] = new int[2]; jagged[1] = new int[5]; System.out.println(jagged[0].length); // 2 System.out.println(jagged[1].length); // 5

3.6 Iterating Over Multi Dimensional Arrays

a) Nested Traditional for Loops

for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { System.out.print(matrix[i][j] + " "); } System.out.println(); }

b) Enhanced for Loops (for-each)

for (int[] row : matrix) { for (int val : row) { System.out.print(val + " "); } System.out.println(); }
  • For 3D arrays, you need three nested loops.

c) Using Arrays.deepToString()

import java.util.Arrays; System.out.println(Arrays.deepToString(matrix));
  • deepToString() works for arrays of arrays; it produces a string representation of the entire structure.

3.7 Common Operations

a) Sum of All Elements

int sum = 0; for (int[] row : matrix) { for (int val : row) { sum += val; } }

b) Matrix Multiplication

int[][] a = {{1, 2}, {3, 4}}; int[][] b = {{5, 6}, {7, 8}}; int[][] result = new int[2][2]; for (int i = 0; i < a.length; i++) { for (int j = 0; j < b[0].length; j++) { for (int k = 0; k < a[0].length; k++) { result[i][j] += a[i][k] * b[k][j]; } } }

c) Transpose of a Matrix

int rows = matrix.length; int cols = matrix[0].length; int[][] transpose = new int[cols][rows]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { transpose[j][i] = matrix[i][j]; } }

3.8 Ragged (Jagged) Arrays

Java allows each inner array to have a different length. This is useful when the data is not rectangular.

int[][] jagged = new int[3][]; jagged[0] = new int[1]; jagged[1] = new int[3]; jagged[2] = new int[2]; // Initialize with values jagged[0][0] = 10; jagged[1][0] = 20; jagged[1][1] = 30; jagged[1][2] = 40; jagged[2][0] = 50; jagged[2][1] = 60;

Iterating over jagged array:

for (int i = 0; i < jagged.length; i++) { for (int j = 0; j < jagged[i].length; j++) { System.out.print(jagged[i][j] + " "); } System.out.println(); }

3.9 Multi Dimensional Arrays of Objects

You can create arrays of objects in multiple dimensions.

String[][] names = new String[2][3]; names[0][0] = "Alice"; names[0][1] = "Bob"; names[0][2] = "Charlie"; names[1][0] = "David"; names[1][1] = "Eve"; names[1][2] = "Frank";

Or with initializer:

String[][] names = { {"Alice", "Bob", "Charlie"}, {"David", "Eve", "Frank"} };

3.10 Memory Representation

A 2D array int[3][4] is stored as:

  • One array of 3 elements, each element is a reference to an int[] array.
  • Three separate int[] arrays, each of length 4, stored elsewhere on the heap.

This means:

  • matrix[0] is a reference to an array of 4 ints.
  • matrix[1] is another reference, etc.
  • Accessing matrix[1][2] involves two dereferences: first get the row array, then the element.

Jagged arrays follow the same model, but the inner arrays can have different lengths.


3.11 Common Pitfalls

PitfallExampleSolution
Null row in jagged arrayint[][] jag = new int[2][]; jag[0][0] = 5; → NullPointerExceptionAllocate each row before use
Inconsistent column lengths assumptionfor (int j = 0; j < 3; j++) assuming all rows have 3 columnsUse matrix[i].length
Using matrix.length for columnsmatrix.length gives rows, not columnsUse matrix[0].length only if rectangular
Misplacing brackets in declarationint[] arr[], var; – var is an int, not arrayUse int[][] arr; style
Deep copy vs shallow copyint[][] copy = matrix.clone(); copies only the row referencesUse nested loops or deepCopy method
Index out of boundsAccessing matrix[2][3] in a 2×3 matrixValidate indices with length

3.12 Best Practices

  • Use meaningful names: matrix, grid, table, pixels for 2D; cube, volume for 3D.
  • Use matrix.length for rows and matrix[0].length for columns only when you are certain the array is rectangular.
  • Always check row lengths when iterating jagged arrays.
  • Prefer enhanced for loops for reading; use index loops when you need to modify elements.
  • Use Arrays.deepEquals() and Arrays.deepToString() for deep comparisons and printing.
  • If performance matters, consider that accessing elements in a multi dimensional array involves multiple dereferences. For critical code, sometimes a flat array is faster.
  • When copying multi dimensional arrays, create a deep copy by manually copying each inner array.

3.13 Example: 2D Array Utility Methods

import java.util.Arrays; public class MultiDimExample { // Print 2D array (rectangular or jagged) public static void print2D(int[][] arr) { for (int[] row : arr) { for (int val : row) { System.out.print(val + " "); } System.out.println(); } } // Create a copy (deep copy) of a 2D array public static int[][] deepCopy(int[][] original) { if (original == null) return null; int[][] copy = new int[original.length][]; for (int i = 0; i < original.length; i++) { if (original[i] != null) { copy[i] = Arrays.copyOf(original[i], original[i].length); } } return copy; } public static void main(String[] args) { int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; System.out.println("Matrix:"); print2D(matrix); // Transpose int[][] transpose = new int[matrix[0].length][matrix.length]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { transpose[j][i] = matrix[i][j]; } } System.out.println("Transpose:"); print2D(transpose); // Jagged array example int[][] jagged = { {1}, {2, 3}, {4, 5, 6} }; System.out.println("Jagged array:"); print2D(jagged); // Using deepToString System.out.println(Arrays.deepToString(matrix)); } }

3.14 Multi Dimensional Arrays of More Than Two Dimensions

You can create arrays with any number of dimensions.

int[][][] threeD = new int[3][4][5]; threeD[1][2][3] = 42;

Iteration:

for (int i = 0; i < threeD.length; i++) { for (int j = 0; j < threeD[i].length; j++) { for (int k = 0; k < threeD[i][j].length; k++) { System.out.print(threeD[i][j][k] + " "); } System.out.println(); } System.out.println("---"); }

For very high dimensions, consider alternative data structures or flattening into a 1D array for performance and simplicity.


3.15 Key Points to Remember

  • A multi dimensional array in Java is an array of arrays. Each dimension is a separate array object.
  • Rectangular arrays have all inner arrays of the same length; jagged arrays can have varying lengths.
  • Declaration: int[][] matrix; Creation: new int[rows][cols]; or new int[rows][]; followed by allocating rows individually.
  • The length field on a 2D array gives the number of rows; each row has its own length.
  • Use nested loops or enhanced for loops to iterate.
  • Arrays.deepToString() and Arrays.deepEquals() work on arrays of any depth.
  • Be careful with null rows in jagged arrays and always initialize them before use.
  • Multi dimensional arrays are stored non contiguously; access involves multiple pointer dereferences.

Hi! Need help with studies? 👋
AI