In Java, arrays are objects that store multiple values of the same type. Arrays are indexed collections with a fixed length determined at the time of creation. They are commonly used to store sequences of numbers, strings, objects, or any other data type in contiguous memory.
There are two standard ways to declare an array in Java:
int[] numbers; // Preferred style
int numbers[]; // Also valid, common in C/C++-influenced code
This declaration doesn't allocate memory—it only defines a reference to an array.
After declaring an array, you can initialize it with a specified size:
int[] numbers = new int[5]; // creates an array of 5 integers
This creates an array with indexes 0
to 4
. Each element is initialized to a default value depending on the array's type:
Type | Default Value |
---|---|
int , short , byte , long |
0 |
float , double |
0.0 |
char |
'\u0000' (null character) |
boolean |
false |
Reference types (String , custom classes, etc.) |
null |
Example:
String[] names = new String[3]; // names[0], names[1], names[2] all default to null
You can also initialize an array using array literals:
int[] primes = {2, 3, 5, 7, 11};
String[] fruits = {"Apple", "Banana", "Cherry"};
This automatically sets the size and initializes elements in one line. The compiler counts the number of items and creates the array accordingly.
It is legal to declare and later initialize:
double[] weights;
weights = new double[] {65.5, 70.2, 55.0};
Note: If you're using new type[]
, you must use the new
keyword explicitly when separating declaration and initialization.
Java arrays can be initialized using loops—useful when values follow a pattern:
int[] squares = new int[10];
for (int i = 0; i < squares.length; i++) {
squares[i] = i * i;
}
This sets each index of the squares
array to the square of its index (0, 1, 4, 9, ..., 81
).
public class ArrayDemo {
public static void main(String[] args) {
// Declaration
int[] numbers1; // Preferred style
int numbers2[]; // Also valid
// Initialization with fixed length
numbers1 = new int[5]; // Default values: 0
// Assigning values manually
for (int i = 0; i < numbers1.length; i++) {
numbers1[i] = i + 1;
}
// Literal initialization
int[] primes = {2, 3, 5, 7, 11};
// Separate declaration and initialization
double[] weights;
weights = new double[] {65.5, 70.2, 55.0};
// Reference type array
String[] fruits = new String[3];
fruits[0] = "Apple";
fruits[1] = "Banana";
fruits[2] = "Cherry";
// Initialization with loop (squares of index)
int[] squares = new int[10];
for (int i = 0; i < squares.length; i++) {
squares[i] = i * i;
}
// Output results
System.out.println("Numbers1: ");
for (int n : numbers1) System.out.print(n + " ");
System.out.println();
System.out.println("Primes: ");
for (int p : primes) System.out.print(p + " ");
System.out.println();
System.out.println("Weights: ");
for (double w : weights) System.out.print(w + " ");
System.out.println();
System.out.println("Fruits: ");
for (String f : fruits) System.out.print(f + " ");
System.out.println();
System.out.println("Squares: ");
for (int s : squares) System.out.print(s + " ");
System.out.println();
}
}
While arrays in Java are useful for storing fixed-size sequences, they come with limitations:
ArrayList
or other classes from the java.util
package.0
, which can lead to off-by-one errors if not carefully managed.Despite their limitations, arrays are efficient and straightforward, making them a good choice for fixed-size data and performance-sensitive applications.
In Java, multidimensional arrays are arrays of arrays. The most common use is the two-dimensional array (2D array), often visualized as a table or matrix with rows and columns. Java also supports jagged arrays, where each row can have a different length, providing greater flexibility.
A rectangular 2D array is one where each row has the same number of columns.
Declaration and initialization:
int[][] matrix = new int[3][4]; // 3 rows, 4 columns
This creates a grid like:
[ [0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0] ]
Each int
element is initialized to 0
by default.
Alternative declaration with values:
int[][] matrix = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 0, 1, 2}
};
Here, the size is inferred from the initializer: 3
rows and 4
columns.
A jagged array allows each row to have a different length:
int[][] triangle = new int[3][];
triangle[0] = new int[1]; // Row 0 has 1 column
triangle[1] = new int[2]; // Row 1 has 2 columns
triangle[2] = new int[3]; // Row 2 has 3 columns
This creates a triangular structure often used in algorithms like Pascal's Triangle or in graphics buffers.
With values:
int[][] triangle = {
{1},
{2, 3},
{4, 5, 6}
};
To work with individual elements of a 2D array, use two indices:
int value = matrix[1][2]; // Access value in 2nd row, 3rd column
matrix[0][0] = 99; // Assign value to 1st row, 1st column
Note that indexing starts at 0
, so matrix[1][2]
accesses the second row and third column.
You can use nested loops to iterate over a 2D array:
for (int i = 0; i < matrix.length; i++) { // Rows
for (int j = 0; j < matrix[i].length; j++) { // Columns
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
Using matrix.length
gives the number of rows, and matrix[i].length
gives the number of columns in row i
—which is especially important for jagged arrays.
public class TwoDArrayDemo {
public static void main(String[] args) {
// Rectangular 2D array declaration and initialization
int[][] matrix = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 0, 1, 2}
};
// Access and modify elements
matrix[0][0] = 99;
int value = matrix[1][2];
System.out.println("Rectangular matrix:");
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();
}
System.out.println("\nValue at matrix[1][2]: " + value);
// Jagged array declaration
int[][] triangle = new int[3][];
triangle[0] = new int[] {1};
triangle[1] = new int[] {2, 3};
triangle[2] = new int[] {4, 5, 6};
System.out.println("\nJagged triangle array:");
for (int i = 0; i < triangle.length; i++) {
for (int j = 0; j < triangle[i].length; j++) {
System.out.print(triangle[i][j] + " ");
}
System.out.println();
}
}
}
Multidimensional arrays are well-suited to tabular data, such as:
[row][column]
)Readability can become an issue with deep nesting, especially in jagged arrays. It's important to use clear variable names and formatting to make code easier to understand.
NullPointerException
.Multidimensional arrays are powerful tools in Java for modeling structured data. Choosing between rectangular and jagged arrays depends on the problem domain and how uniform the data is. In the next section, we'll look at how to access array elements and determine their length dynamically.
Once an array is declared and initialized, you can access and modify its elements using index-based notation. Arrays in Java use zero-based indexing, meaning the first element is at index 0
, the second at index 1
, and so on.
To read an element from an array, use square brackets:
int[] numbers = {10, 20, 30, 40};
int first = numbers[0]; // Gets 10
int last = numbers[3]; // Gets 40
To write or update an element:
numbers[1] = 25; // Now numbers = {10, 25, 30, 40}
Accessing an index outside the valid range will throw an exception:
numbers[4] = 50; // Throws ArrayIndexOutOfBoundsException
Always ensure that the index is greater than or equal to 0 and less than array.length
.
Java arrays have a public length
field, which holds the number of elements in the array.
int size = numbers.length; // 4
❗Note: This is not a method—there are no parentheses.
To avoid ArrayIndexOutOfBoundsException
, use .length
when iterating:
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
Using .length
in loops ensures that your code stays flexible and resilient to size changes:
String[] fruits = {"Apple", "Banana", "Cherry"};
for (int i = 0; i < fruits.length; i++) {
System.out.println("Fruit " + i + ": " + fruits[i]);
}
This pattern avoids hardcoding array sizes and improves maintainability.
.length
vs. .length()
vs. .size()
It's important to distinguish between how different types expose their size:
Type | Syntax | Notes |
---|---|---|
Array | array.length |
Public field, no parentheses |
String | str.length() |
Method call |
Collection/List | list.size() |
Method call |
Example:
String text = "Hello";
System.out.println(text.length()); // 5
int[] values = {1, 2, 3};
System.out.println(values.length); // 3
Confusing these can lead to compilation errors.
public class ArrayAccessDemo {
public static void main(String[] args) {
// Accessing array elements
int[] numbers = {10, 20, 30, 40};
int first = numbers[0]; // 10
int last = numbers[3]; // 40
System.out.println("First element: " + first);
System.out.println("Last element: " + last);
// Modifying an element
numbers[1] = 25; // Now numbers = {10, 25, 30, 40}
System.out.println("Modified second element: " + numbers[1]);
// Getting array length
System.out.println("Array length: " + numbers.length);
// Safe iteration
System.out.println("All elements:");
for (int i = 0; i < numbers.length; i++) {
System.out.println("numbers[" + i + "] = " + numbers[i]);
}
// Demonstrating ArrayIndexOutOfBoundsException
try {
numbers[4] = 50; // Invalid index
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Caught exception: " + e);
}
// Comparing .length, .length(), and .size()
String text = "Hello";
System.out.println("String length: " + text.length());
int[] values = {1, 2, 3};
System.out.println("Array length: " + values.length);
}
}
Accessing array elements and knowing their length is foundational to array manipulation. By using .length
properly, you can avoid common pitfalls like index-out-of-bounds errors. Understanding the differences between .length
, .length()
, and .size()
helps prevent subtle bugs, especially when transitioning between arrays, strings, and collections.
Java provides an enhanced for
loop (also known as the for-each loop) to simplify iteration over arrays. It offers a concise and readable way to loop through each element, especially when you don't need the index or aren't modifying the array.
The enhanced for
loop follows this structure:
for (type variable : array) {
// Use variable
}
Here's a basic example:
int[] numbers = {10, 20, 30, 40};
for (int num : numbers) {
System.out.println("Number: " + num);
}
In this case, num
takes on the value of each element in the numbers
array, one at a time. You cannot use num
to modify the original array elements—changes to num
do not affect the array.
The enhanced loop also works well with arrays of objects:
String[] fruits = {"Apple", "Banana", "Cherry"};
for (String fruit : fruits) {
System.out.println("Fruit: " + fruit);
}
This makes iterating through strings, custom objects, and other types much simpler and less error-prone.
While convenient, there are times when the enhanced for
loop is not suitable:
Modifying elements in place: You cannot change values in the original array directly.
for (int num : numbers) {
num = num * 2; // This does NOT change the actual array
}
Accessing by index: If you need to know the position of the element or compare elements by index, use a traditional for
loop:
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[i] * 2; // This correctly updates the array
}
public class EnhancedForLoopDemo {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40};
System.out.println("Using enhanced for loop:");
for (int num : numbers) {
System.out.println("Number: " + num);
}
System.out.println("\nAttempting to modify array (fails silently):");
for (int num : numbers) {
num = num * 2; // This does not affect the original array
}
// Show that original array is unchanged
for (int num : numbers) {
System.out.println("Still original: " + num);
}
System.out.println("\nModifying array using traditional for loop:");
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[i] * 2;
}
for (int num : numbers) {
System.out.println("Modified: " + num);
}
System.out.println("\nEnhanced for loop with reference types:");
String[] fruits = {"Apple", "Banana", "Cherry"};
for (String fruit : fruits) {
System.out.println("Fruit: " + fruit);
}
}
}
The enhanced for
loop improves readability and reduces boilerplate when you simply want to process each element without modifying them or tracking indexes. It shines in scenarios like printing values, summing numbers, or checking conditions.
However, when you need control over the index—such as replacing elements, accessing adjacent values, or skipping certain items—a classic index-based loop remains the better choice.
In general, prefer enhanced for
loops for cleaner and more declarative code, and fall back to index-based loops when precision and mutation are required.