An array is a container object that holds a
fixed number of values of a
single type. Once created, the size of an array
cannot be changed. Arrays in Java are zero-indexed,
meaning the first element is at index 0,
the second at index 1, and so on up to
length - 1.
// Conceptual diagram of an int array with 5 elements: // // Index: [0] [1] [2] [3] [4] // -----+-----+-----+-----+----- // Value: | 10 | 20 | 30 | 40 | 50 | // -----+-----+-----+-----+----- // // - Fixed size: always 5 elements // - Same type: all are int // - Zero-indexed: first element is at index 0
Arrays are objects in Java — they are stored on the heap. The variable you declare holds a reference to the array object, not the array itself.
When to use arrays: Arrays are ideal when you
know the exact number of elements in advance and need fast
index-based access. For dynamic sizing, prefer
ArrayList from the Collections
framework.
There are three common ways to declare and initialize arrays in Java:
// Step 1: Declare the array reference int[] scores; // Step 2: Allocate memory with 'new' — elements default to 0 scores = new int[5]; // Step 3: Assign values individually scores[0] = 95; scores[1] = 88; scores[2] = 76; scores[3] = 91; scores[4] = 83;
// All in one statement
String[] days = new String[]{"Mon", "Tue", "Wed", "Thu", "Fri"};
// Most concise — no 'new' keyword needed
double[] prices = {9.99, 14.50, 3.75, 22.00};
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
Default values when an array is created with
new but not explicitly initialized:
| Type | Default Value |
|---|---|
int,
long,
short,
byte
|
0 |
float,
double
|
0.0 |
boolean |
false |
char |
'\\u0000' |
Java arrays are fixed-size objects that store values of one declared
type. They are zero-indexed, so valid positions range from
0 to
array.length - 1. The
length property is a field, not a method.
| Characteristic | Meaning |
|---|---|
| Fixed size | The length is decided when the array is created. |
| Single type | Every element uses the declared primitive or reference type. |
| Zero-indexed | The first item is at index 0 and the last is length minus 1. |
| Object in Java | An array is allocated on the heap and the variable stores its reference. |
| Direct access | Reading or writing a known index is generally an O(1) operation. |
Use arrays when: the number of elements is known, indexed access matters, or primitive values should be stored without collection boxing.
Use square brackets to read or replace an element. An invalid index
throws ArrayIndexOutOfBoundsException.
Use an index-based loop when the position is needed and an enhanced
loop when only the value is required.
// Read and update values
int[] scores = {85, 92, 78};
int first = scores[0]; // 85
scores[2] = 81; // replace 78
System.out.println(scores.length); // 3
for (int index = 0; index < scores.length; index++) {
System.out.println(index + ": " + scores[index]);
}
for (int score : scores) {
System.out.println(score);
}
Assigning the enhanced-loop variable does not update the array. Use an index-based loop when you need to modify elements in place.
An array variable holds a reference to an array object. Primitive arrays store primitive values, while reference arrays store references to other objects. Assigning one array variable to another copies the reference, not the elements.
int[] original = {1, 2, 3};
int[] alias = original;
alias[0] = 99; // original[0] is also 99
int[] copy = java.util.Arrays.copyOf(original, original.length);
copy[0] = 1; // original is unaffected
Use Arrays.copyOf or another deliberate
copying strategy when callers should not share mutable array state.
Java models a multidimensional array as an array whose elements are other arrays. A two-dimensional array is useful for grids and matrix-like data. Each row is a separate array object.
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int row = 0; row < matrix.length; row++) {
for (int column = 0; column < matrix[row].length; column++) {
System.out.print(matrix[row][column] + " ");
}
System.out.println();
}
Because each row is independent, rows may have different lengths.
This is a jagged or ragged array. Always use
matrix[row].length for the current row.
int[][] jagged = new int[3][]; jagged[0] = new int[2]; jagged[1] = new int[4]; jagged[2] = new int[1];
The java.util.Arrays class provides
tested helpers for sorting, searching, copying, comparing, and
printing arrays.
import java.util.Arrays;
int[] values = {40, 10, 30, 20};
Arrays.sort(values); // [10, 20, 30, 40]
int position = Arrays.binarySearch(values, 30); // 2
int[] larger = Arrays.copyOf(values, 6);
Arrays.fill(larger, 4, 6, 0);
System.out.println(Arrays.toString(values));
int[][] left = {{1, 2}, {3, 4}};
int[][] right = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepEquals(left, right)); // true
Remember: call binarySearch only on a sorted array. For nested arrays, use deepToString and deepEquals.
| Advantage | Limitation |
|---|---|
| Fast direct access by index | Length cannot grow or shrink |
| Low overhead for primitive values | Insertion and deletion require shifting or copying |
| Strong compile-time element type | Only one element type is supported |
| Useful for fixed-size data | Few operations are available directly on the array |
Choose an array when size and indexed access are central to the problem. Choose a collection when data grows, shrinks, or needs higher-level operations such as filtering and membership checks.
| Feature | Array | ArrayList |
|---|---|---|
| Size | Fixed after creation | Dynamic capacity |
| Primitive values | Supported directly | Uses wrapper objects and boxing |
| API | length and utility methods | add, remove, and contains |
| Generics | Generic arrays cannot be created directly | Works with List<T> |
int[] fixedScores = {80, 90, 85};
java.util.List<Integer> changingScores = new java.util.ArrayList<>();
changingScores.add(80);
changingScores.add(90);
static void reverse(int[] values) {
int left = 0;
int right = values.length - 1;
while (left < right) {
int temporary = values[left];
values[left++] = values[right];
values[right--] = temporary;
}
}
static int missingNumber(int[] values, int n) {
int expected = n * (n + 1) / 2;
int actual = 0;
for (int value : values) actual += value;
return expected - actual;
}
// missingNumber(new int[]{1, 2, 4, 5, 6}, 6) returns 3
static void rotateRight(int[] values, int steps) {
if (values.length == 0) return;
steps %= values.length;
reverse(values, 0, values.length - 1);
reverse(values, 0, steps - 1);
reverse(values, steps, values.length - 1);
}
static int[] twoSum(int[] values, int target) {
java.util.Map<Integer, Integer> seen = new java.util.HashMap<>();
for (int index = 0; index < values.length; index++) {
int needed = target - values[index];
if (seen.containsKey(needed)) return new int[]{seen.get(needed), index};
seen.put(values[index], index);
}
throw new IllegalArgumentException("No pair found");
}
Reverse and rotation use O(1) extra space. The missing-number solution uses O(n) time and O(1) extra space, while the hash-map two-sum solution uses O(n) additional space to achieve O(n) time.
int[] values rather than the less readable int values[].array.length, not array.length().Arrays.equals instead of == when comparing contents.ArrayList when the number of values changes frequently.