We are going to learn Java Arrays from absolute beginner level through practical coding, internal behavior, common mistakes, production usage, revision, and interview preparation. This chapter includes declaration, creation, initialization, indexing, one-dimensional and multidimensional arrays, jagged arrays, traversal, arrays with methods and objects, copying, sorting, searching, comparing, filling, java.util.Arrays, and common array exceptions.
Imagine that you are building a small application.
You need to store the marks of one student.
That is easy:
int mark = 80;Now suppose you need to store marks for five students.
You could write:
int mark1 = 80;
int mark2 = 75;
int mark3 = 90;
int mark4 = 65;
int mark5 = 88;For five values, this may still look manageable.
But now imagine:
- 100 students
- 1,000 employees
- 10,000 product prices
- thousands of sensor readings
Would you create thousands of separate variables?
Obviously, that would become difficult to write, process, search, sort, and maintain.
What we need is one variable capable of representing multiple values of the same type.
That brings us to one of Java's fundamental data structures.
1. What Is an Array?#
An array is an object that stores a fixed number of values of the same type.
For example:
int[] marks = {80, 75, 90, 65, 88};Here:
marksis an array variable.- It represents five
intvalues. - All elements are of type
int. - Each value has a numeric position called an index.
Think of the array like numbered storage boxes:
Array: marks
Index 0 1 2 3 4
┌────┬────┬────┬────┬────┐
Value │ 80 │ 75 │ 90 │ 65 │ 88 │
└────┴────┴────┴────┴────┘Notice something important:
The first position is 0, not 1.
We will shortly understand why indexing matters.
Simple definition#
A Java array is a fixed-size object containing multiple elements of one declared type, where each element is accessed using an integer index.
2. Why Are Arrays Used?#
Before arrays, suppose we had:
int mark1 = 80;
int mark2 = 75;
int mark3 = 90;
int mark4 = 65;
int mark5 = 88;How would you calculate their total?
int total = mark1 + mark2 + mark3 + mark4 + mark5;Now imagine 1,000 marks.
This design does not scale.
With an array:
int[] marks = {80, 75, 90, 65, 88};
int total = 0;
for (int mark : marks) {
total += mark;
}
System.out.println(total);Arrays provide several advantages:
- Store many related values under one variable.
- Access individual values using indexes.
- Process elements using loops.
- Pass a group of values to a method.
- Return groups of values from methods.
- Sort and search collections of values.
- Represent matrices and tabular structures.
- Build many higher-level data structures.
Arrays are also fundamental to Java because structures such as:
String[] argsin the main() method are themselves arrays.
3. An Important Mental Model#
An array variable does not contain all elements directly in the ordinary local variable itself.
An array is an object.
Consider:
int[] numbers = new int[3];Conceptually:
Local variable
numbers
│
│ reference
▼
Heap memory
┌───────────────┐
│ int[] object │
├───────────────┤
│ 0 │ 0 │ 0 │
└───────────────┘numbers contains a reference to the array object.
This becomes very important when we discuss:
- assignment
- passing arrays to methods
- copying
- comparison
- mutation
4. Array Declaration#
Before using an array, we need to tell Java what type of array variable we want.
The preferred Java syntax is:
int[] numbers;This means:
numberscan refer to an array whose elements areint.
Another legal form is:
int numbers[];Both compile.
However, this is generally preferred:
int[] numbers;Why?
Because the type visually appears together:
int[]meaning:
array of int
For example:
double[] prices;
String[] names;
char[] letters;
boolean[] flags;At this point, only the reference variable has been declared.
No array object has necessarily been created yet.
For example:
int[] numbers;does not by itself create space for five integers.
That requires array creation.
5. Array Creation#
Now we need an actual array object.
Java uses the new keyword:
int[] numbers = new int[5];Let's break this down:
int[] numbers = new int[5];
│ │ │
type variable create arraynew int[5] creates an array capable of storing exactly five int elements.
Conceptually:
numbers
│
▼
┌────┬────┬────┬────┬────┐
│ 0 │ 0 │ 0 │ 0 │ 0 │
└────┴────┴────┴────┴────┘
0 1 2 3 4Notice that Java automatically initializes the elements.
We did not assign those zeros ourselves.
That leads us to an important rule.
6. Default Values in Arrays#
When Java creates an array, its elements receive default values.
| Element Type | Default Value |
|---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
char | '\u0000' |
boolean | false |
| Reference types | null |
Example:
public class ArrayDefaults {
public static void main(String[] args) {
int[] numbers = new int[3];
System.out.println(numbers[0]);
System.out.println(numbers[1]);
System.out.println(numbers[2]);
}
}Output:
0
0
0Now consider:
String[] names = new String[3];Its conceptual state is:
Index 0 1 2
┌──────┬──────┬──────┐
Value │ null │ null │ null │
└──────┴──────┴──────┘This is especially important because using an element before assigning an object may later cause a NullPointerException.
7. Array Initialization#
We have learned that:
int[] numbers = new int[5];creates an array using default values.
But frequently we already know the values.
Then we can initialize the array directly:
int[] numbers = {10, 20, 30, 40, 50};Java determines the size automatically.
Equivalent conceptual result:
Index 0 1 2 3 4
┌────┬────┬────┬────┬────┐
Value │ 10 │ 20 │ 30 │ 40 │ 50 │
└────┴────┴────┴────┴────┘Another form is:
int[] numbers = new int[]{10, 20, 30, 40, 50};Both are valid during declaration.
But notice this:
int[] numbers;
numbers = {10, 20, 30};This is invalid Java.
If initialization occurs separately, use:
int[] numbers;
numbers = new int[]{10, 20, 30};Why?#
The compact {...} initializer syntax is permitted as part of an array variable declaration.
For a later assignment, Java requires an explicit array creation expression.
8. Array Index#
Suppose:
int[] numbers = {10, 20, 30, 40};Java assigns indexes:
Index 0 1 2 3
┌────┬────┬────┬────┐
Value │ 10 │ 20 │ 30 │ 40 │
└────┴────┴────┴────┘The array contains four elements.
However, the valid indexes are:
0
1
2
3The rule is:
First valid index = 0
Last valid index = length - 1For an array whose length is 4:
last index = 4 - 1 = 3This rule is extremely important.
Many beginner array bugs come from confusing:
lengthwith:
last indexThey are not the same.
9. Accessing Array Elements#
To access an element, use:
arrayName[index]Example:
public class AccessArray {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40};
System.out.println(numbers[0]);
System.out.println(numbers[2]);
}
}Output:
10
30Let's visualize:
numbers[0] → 10
numbers[1] → 20
numbers[2] → 30
numbers[3] → 4010. Updating Array Elements#
Array elements are mutable.
That means we can replace an existing element.
Example:
int[] numbers = {10, 20, 30};
numbers[1] = 500;Before:
[10, 20, 30]After:
[10, 500, 30]Complete example:
public class UpdateArray {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
numbers[1] = 500;
System.out.println(numbers[1]);
}
}Output:
500One important distinction:
The contents can change.
The length cannot change after array creation.
11. Fixed Size — A Fundamental Property#
Consider:
int[] numbers = new int[5];The length is permanently 5 for that array object.
You cannot later say:
numbers.length = 10;That does not compile.
You can make numbers refer to a different array:
numbers = new int[10];But that creates another array object.
It does not resize the original array.
Conceptually:
Before
numbers ──► int[5]
After
numbers ──► int[10]The original int[5] becomes eligible for garbage collection if nothing else references it.
This fixed-size characteristic is one major difference between Java arrays and dynamic collections such as ArrayList.
12. Array Length#
Every Java array has a field called:
lengthExample:
int[] numbers = {10, 20, 30, 40};
System.out.println(numbers.length);Output:
4Notice:
numbers.lengthnot:
numbers.length()Why?
Because length is a field of an array, not a method call.
This is commonly confused with:
String.length()and:
ArrayList.size()Comparison:
| Structure | Size operation |
|---|---|
| Array | array.length |
| String | string.length() |
| ArrayList | list.size() |
This is a very common interview and beginner question.
13. One-Dimensional Arrays#
Until now, our arrays have been one-dimensional.
Example:
int[] scores = {90, 80, 70, 60};Conceptually:
[90] [80] [70] [60]You can think of this as one sequence of elements.
A complete example:
public class OneDimensionalArray {
public static void main(String[] args) {
String[] cities = {"Pune", "Mumbai", "Delhi"};
System.out.println(cities[0]);
System.out.println(cities[1]);
System.out.println(cities[2]);
}
}Output:
Pune
Mumbai
Delhi14. Array Traversal#
Suppose an array contains 1,000 elements.
Would you write:
System.out.println(numbers[0]);
System.out.println(numbers[1]);
System.out.println(numbers[2]);one thousand times?
No.
We use loops.
Processing elements sequentially is called array traversal.
15. Traversing with a Traditional for Loop#
Example:
public class ArrayTraversal {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40};
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
}
}Output:
10
20
30
40Let's understand the loop:
for (int i = 0; i < numbers.length; i++)We start:
i = 0because the first index is 0.
We continue while:
i < numbers.lengthFor a length of 4:
i = 0, 1, 2, 3When i becomes 4:
4 < 4is false.
Therefore the loop ends safely.
16. A Classic Off-by-One Error#
Look carefully:
for (int i = 0; i <= numbers.length; i++) {
System.out.println(numbers[i]);
}What is wrong?
Suppose:
numbers.length == 4Because of:
i <= numbers.lengththe loop eventually allows:
i == 4Then Java tries:
numbers[4]But valid indexes are only:
0, 1, 2, 3The result is:
ArrayIndexOutOfBoundsExceptionCorrect:
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}Memory rule#
Array traversal by index:
0 <= index < array.length17. Enhanced for Loop with Arrays#
Sometimes we don't care about indexes.
We simply want every value.
Instead of:
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}we can write:
for (int number : numbers) {
System.out.println(number);
}This syntax is called:
- enhanced
forloop - for-each loop
Read it naturally as:
For eachnumberinnumbers.
Example:
public class EnhancedForExample {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
for (int number : numbers) {
System.out.println(number);
}
}
}Output:
10
20
3018. Traditional for vs Enhanced for#
These loops are related but serve different needs.
| Requirement | Traditional for | Enhanced for |
|---|---|---|
| Read every element | Yes | Yes |
| Need index | Yes | No direct index |
| Modify array by index | Excellent | Not directly |
| Traverse backwards | Yes | No |
| Skip indexes easily | Yes | Less suitable |
| Simple sequential reading | More verbose | Excellent |
Decision rule:
Need the index?
→ traditional for
Need custom traversal direction?
→ traditional for
Need to replace array elements?
→ traditional for
Only need to read each value?
→ enhanced for19. A Very Important Enhanced for Trap#
Consider:
int[] numbers = {10, 20, 30};
for (int number : numbers) {
number = 100;
}Will the array become:
[100, 100, 100]No.
Why?
number receives the element's value.
Changing the local loop variable does not replace the corresponding array slot.
After the loop:
[10, 20, 30]To replace elements:
for (int i = 0; i < numbers.length; i++) {
numbers[i] = 100;
}Now:
[100, 100, 100]20. Two-Dimensional Arrays#
So far our arrays look like a single row:
[10] [20] [30]But suppose we need to represent student marks across subjects:
Java SQL Angular
Student 1 80 90 75
Student 2 70 85 88One-dimensional representation becomes less natural.
We need rows and columns.
That leads to a two-dimensional array.
int[][] marks = {
{80, 90, 75},
{70, 85, 88}
};Conceptually:
Column
0 1 2
┌────┬────┬────┐
Row 0 │ 80 │ 90 │ 75 │
├────┼────┼────┤
Row 1 │ 70 │ 85 │ 88 │
└────┴────┴────┘Access:
marks[0][0]returns:
80And:
marks[1][2]returns:
8821. Java's Two-Dimensional Arrays Are Really Arrays of Arrays#
This is important.
Java does not require every row to be part of one flat rectangular object.
Consider:
int[][] matrix = new int[3][4];Conceptually:
matrix
│
▼
┌────────┬────────┬────────┐
│ ref │ ref │ ref │
└───┬────┴───┬────┴───┬────┘
│ │ │
▼ ▼ ▼
[0,0,0,0] [0,0,0,0] [0,0,0,0]The outer array stores references to inner arrays.
This explains why Java supports jagged arrays.
22. Creating a 2D Array#
You can create:
int[][] matrix = new int[2][3];This gives:
2 rows
3 elements per rowAccess:
matrix[0][0] = 10;
matrix[0][1] = 20;
matrix[0][2] = 30;
matrix[1][0] = 40;
matrix[1][1] = 50;
matrix[1][2] = 60;23. Traversing a 2D Array#
We need one loop for rows and another for the elements inside each row.
public class TwoDimensionalTraversal {
public static void main(String[] args) {
int[][] matrix = {
{10, 20, 30},
{40, 50, 60}
};
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();
}
}
}Output:
10 20 30
40 50 60Notice:
matrix.lengthmeans:
number of rows
while:
matrix[row].lengthmeans:
number of elements in that specific row
Using matrix[row].length becomes especially important for jagged arrays.
24. Enhanced for with 2D Arrays#
We can also write:
int[][] matrix = {
{10, 20, 30},
{40, 50, 60}
};
for (int[] row : matrix) {
for (int value : row) {
System.out.print(value + " ");
}
System.out.println();
}Here:
int[] rowmakes sense because each element of:
int[][]is itself an:
int[]That is a useful way to understand multidimensional Java arrays.
25. Multidimensional Arrays#
Java supports arrays with more dimensions.
For example:
int[][][] data = new int[2][3][4];You can think of it as:
array
↓
arrays
↓
arrays
↓
int valuesAccess:
data[0][1][2]However, use higher-dimensional arrays only when the domain genuinely requires them.
Three-dimensional arrays can be useful for things like:
- coordinates
- image data
- simulation grids
- structured numeric datasets
But overly complex multidimensional arrays can become difficult to maintain.
26. Jagged Arrays#
Now something interesting happens because Java's 2D arrays are arrays of arrays.
What if different rows need different lengths?
For example:
Student 1 → 3 courses
Student 2 → 2 courses
Student 3 → 5 coursesA rectangular structure wastes space or does not model the requirement naturally.
Java allows:
int[][] data = new int[3][];
data[0] = new int[3];
data[1] = new int[2];
data[2] = new int[5];Conceptually:
data
│
├──► [0][0][0]
│
├──► [0][0]
│
└──► [0][0][0][0][0]This is called a jagged array.
Example with values:
int[][] marks = {
{80, 90, 70},
{75, 85},
{60, 70, 80, 90}
};This is legal Java.
27. Traversing a Jagged Array Correctly#
This is correct:
for (int row = 0; row < marks.length; row++) {
for (int column = 0; column < marks[row].length; column++) {
System.out.println(marks[row][column]);
}
}Do not assume:
marks[0].lengthis the length of every row.
Each row may differ.
28. Passing Arrays to Methods#
Suppose we frequently calculate totals.
Instead of repeating the logic:
int total = 0;
for (int number : numbers) {
total += number;
}we can place it inside a method.
public class ArrayMethodExample {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
printArray(numbers);
}
static void printArray(int[] values) {
for (int value : values) {
System.out.println(value);
}
}
}The parameter:
int[] valuesmeans:
This method expects a reference to an int[].29. Does Java Copy the Whole Array When Passing It?#
This is an important interview concept.
Consider:
int[] numbers = {10, 20, 30};
change(numbers);Java is always pass-by-value.
But what value is being passed here?
The value stored in numbers is an array reference.
A copy of that reference value is passed.
So both references point to the same array object.
Example:
public class ArrayMutation {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
change(numbers);
System.out.println(numbers[0]);
}
static void change(int[] values) {
values[0] = 999;
}
}Output:
999Conceptually:
main:
numbers ────────────┐
│
▼
[10, 20, 30]
▲
│
method:
values ─────────────┘Then:
values[0] = 999;changes the shared array object.
30. But Reassigning the Parameter Is Different#
Consider:
public class ArrayReassignment {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
replace(numbers);
System.out.println(numbers[0]);
}
static void replace(int[] values) {
values = new int[]{100, 200, 300};
}
}Output:
10Why?
The method received a copy of the original reference.
Then:
values = new int[]{100, 200, 300};changes only the method's local reference.
Conceptually:
Before reassignment
numbers ────┐
▼
[10,20,30]
▲
values ─────┘
After reassignment
numbers ─────► [10,20,30]
values ──────► [100,200,300]Important interview rule#
Java is always pass-by-value. For arrays, the passed value is a copy of the array reference.
31. Returning Arrays from Methods#
A method can also create and return an array.
Example:
public class ReturnArrayExample {
public static void main(String[] args) {
int[] result = createNumbers();
for (int value : result) {
System.out.println(value);
}
}
static int[] createNumbers() {
return new int[]{10, 20, 30};
}
}The method return type is:
int[]because the method returns an array of integers.
32. Array of Objects#
Until now we mostly stored primitive values:
int[]
double[]
char[]But an array can also store references to objects.
Consider:
String[] names = new String[3];String is a reference type.
Initially:
[null, null, null]Then:
names[0] = "Amit";
names[1] = "Neha";
names[2] = "Rahul";Now:
names
│
├──► "Amit"
├──► "Neha"
└──► "Rahul"33. Custom Objects in Arrays#
Suppose:
class Employee {
String name;
Employee(String name) {
this.name = name;
}
}Now:
Employee[] employees = new Employee[3];A beginner often assumes this creates three Employee objects.
It does not.
It creates an array capable of holding three Employee references.
Initially:
[null, null, null]We still need:
employees[0] = new Employee("Amit");
employees[1] = new Employee("Neha");
employees[2] = new Employee("Rahul");Complete example:
public class ObjectArrayExample {
public static void main(String[] args) {
Employee[] employees = new Employee[3];
employees[0] = new Employee("Amit");
employees[1] = new Employee("Neha");
employees[2] = new Employee("Rahul");
for (Employee employee : employees) {
System.out.println(employee.name);
}
}
}
class Employee {
String name;
Employee(String name) {
this.name = name;
}
}Output:
Amit
Neha
Rahul34. A Common Object Array Mistake#
This code:
Employee[] employees = new Employee[3];
System.out.println(employees[0].name);causes a runtime problem.
Why?
Because:
employees[0]is currently:
nullThen Java effectively tries to access:
null.namewhich produces:
NullPointerExceptionCorrect approach:
employees[0] = new Employee("Amit");
System.out.println(employees[0].name);35. Array Assignment Does Not Copy Elements#
Now we reach one of the most misunderstood topics.
Consider:
int[] first = {10, 20, 30};
int[] second = first;Did Java create another array?
No.
Both variables refer to the same array.
first ──────┐
▼
[10,20,30]
▲
second ─────┘So:
second[0] = 999;also affects what is seen through first.
Example:
public class ArrayReferenceAssignment {
public static void main(String[] args) {
int[] first = {10, 20, 30};
int[] second = first;
second[0] = 999;
System.out.println(first[0]);
}
}Output:
999This is reference assignment, not array copying.
36. Copying Arrays#
Sometimes we genuinely want a second array.
Java offers several approaches:
- manual loop
clone()System.arraycopy()Arrays.copyOf()Arrays.copyOfRange()
Each has useful scenarios.
37. Copying with a Loop#
The most educational approach is:
int[] source = {10, 20, 30};
int[] copy = new int[source.length];
for (int i = 0; i < source.length; i++) {
copy[i] = source[i];
}Now there are two independent primitive arrays:
source ───► [10,20,30]
copy ─────► [10,20,30]If:
copy[0] = 999;the source remains unchanged.
38. clone()#
Arrays support cloning:
int[] source = {10, 20, 30};
int[] copy = source.clone();For a one-dimensional primitive array, this copies the primitive values.
Example:
copy[0] = 999;
System.out.println(source[0]);Output:
10However, when an array contains object references, cloning the array does not clone the referenced objects.
That distinction is called shallow copying.
We will revisit it shortly.
39. System.arraycopy()#
Java provides:
System.arraycopy(
source,
sourcePosition,
destination,
destinationPosition,
length
);Example:
public class ArrayCopyExample {
public static void main(String[] args) {
int[] source = {10, 20, 30, 40, 50};
int[] destination = new int[5];
System.arraycopy(source, 0, destination, 0, source.length);
for (int value : destination) {
System.out.println(value);
}
}
}Output:
10
20
30
40
50The call:
System.arraycopy(source, 0, destination, 0, source.length);means:
source array → source
start from → index 0
destination array → destination
write from → index 0
number of elements → source.length40. Partial Copy with System.arraycopy()#
Suppose:
int[] source = {10, 20, 30, 40, 50};
int[] destination = new int[3];We want:
[20, 30, 40]Use:
System.arraycopy(source, 1, destination, 0, 3);Meaning:
source index 1 → 20
copy 3 elements
destination starts at index 0Result:
[20, 30, 40]41. Arrays.copyOf()#
Before using this method, a new class appears:
java.util.ArraysThe Arrays class contains static utility methods designed for arrays.
Import it:
import java.util.Arrays;Then:
int[] source = {10, 20, 30};
int[] copy = Arrays.copyOf(source, source.length);You can also request a different length:
int[] copy = Arrays.copyOf(source, 5);If the source is:
[10, 20, 30]the new result becomes:
[10, 20, 30, 0, 0]because extra primitive elements receive default values.
42. Arrays.copyOfRange()#
Suppose:
int[] numbers = {10, 20, 30, 40, 50};We want:
[20, 30, 40]Use:
int[] result = Arrays.copyOfRange(numbers, 1, 4);The range follows:
from index → inclusive
to index → exclusiveSo:
1 included
4 excludedElements copied:
index 1 → 20
index 2 → 30
index 3 → 40Result:
[20, 30, 40]This inclusive/exclusive rule is an important interview detail.
43. Shallow Copy with Object Arrays#
Suppose:
Employee[] original = {
new Employee("Amit"),
new Employee("Neha")
};
Employee[] copy = original.clone();There are two different array objects.
But their elements point to the same Employee objects.
Conceptually:
original ──► [ref A][ref B]
│ │
│ └────► Employee("Neha")
└───────────► Employee("Amit")
copy ─────► [ref A][ref B]Therefore:
copy[0].name = "Changed";also changes what:
original[0].nameshows.
This is called a shallow copy.
A deep copy would require creating independent copies of the referenced mutable objects.
44. Sorting Arrays#
Suppose:
int[] numbers = {40, 10, 30, 20};You could manually implement a sorting algorithm.
But for ordinary Java application code, Java provides:
Arrays.sort(numbers);Example:
import java.util.Arrays;
public class SortArrayExample {
public static void main(String[] args) {
int[] numbers = {40, 10, 30, 20};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers));
}
}Output:
[10, 20, 30, 40]Notice:
Arrays.sort(numbers);modifies the existing array.
It does not normally return a new sorted array.
45. Sorting Object Arrays#
For types such as String:
String[] names = {"Rahul", "Amit", "Neha"};
Arrays.sort(names);Result:
[Amit, Neha, Rahul]For custom objects, ordering must be defined using mechanisms such as:
ComparableComparator
Those are larger concepts belonging primarily to object ordering and collections, so we will not turn this arrays chapter into a complete comparator course.
But you should understand this boundary:
Java can directly sort primitive arrays and naturally comparable object arrays. Custom ordering requires an ordering rule.
46. Searching Arrays#
Suppose an array contains:
[10, 20, 30, 40, 50]We want to find 30.
The simplest approach is a linear search:
public class LinearSearchExample {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40, 50};
int target = 30;
int foundIndex = -1;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == target) {
foundIndex = i;
break;
}
}
System.out.println(foundIndex);
}
}Output:
2We used:
-1to mean:
Not found yet.
47. Binary Search#
For sorted data, Java provides:
Arrays.binarySearch()Example:
import java.util.Arrays;
public class BinarySearchExample {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40, 50};
int index = Arrays.binarySearch(numbers, 30);
System.out.println(index);
}
}Output:
2But there is an important prerequisite:
Use Arrays.binarySearch() meaningfully on data sorted according to the expected ordering.Do not assume that calling it on an unsorted array provides a meaningful search result.
48. When binarySearch() Does Not Find the Value#
This is a common interview trap.
Suppose:
int[] numbers = {10, 20, 30, 40};
System.out.println(Arrays.binarySearch(numbers, 25));The return is not simply -1 in every missing case.
The method returns:
-(insertion point) - 1The insertion point for 25 would be index 2.
Therefore:
-(2) - 1 = -3So output:
-3Why encode the insertion position?
Because the caller can determine where the absent element would belong while preserving sorted order.
49. Comparing Arrays#
Now suppose:
int[] first = {10, 20, 30};
int[] second = {10, 20, 30};A beginner may write:
System.out.println(first == second);What does == compare here?
The references.
These are two different arrays.
Therefore:
falseTo compare contents:
Arrays.equals(first, second)returns:
trueExample:
import java.util.Arrays;
public class CompareArrays {
public static void main(String[] args) {
int[] first = {10, 20, 30};
int[] second = {10, 20, 30};
System.out.println(first == second);
System.out.println(Arrays.equals(first, second));
}
}Output:
false
true50. == vs Arrays.equals()#
| Question | == | Arrays.equals() |
|---|---|---|
| Same array reference? | Yes | Not its main purpose |
| Same element contents? | No | Yes |
| Useful for primitive array content comparison? | No | Yes |
Memory rule:
Same object?
→ ==
Same one-dimensional array contents?
→ Arrays.equals()51. Comparing Nested Arrays#
Consider:
int[][] first = {
{1, 2},
{3, 4}
};
int[][] second = {
{1, 2},
{3, 4}
};For nested array content comparison, use:
Arrays.deepEquals(first, second);This performs nested content comparison.
Similarly, nested arrays can be rendered with:
Arrays.deepToString(array);52. Printing Arrays Correctly#
Consider:
int[] numbers = {10, 20, 30};
System.out.println(numbers);You should not expect:
[10, 20, 30]Arrays do not override object string rendering in a way that directly prints their contents.
For one-dimensional arrays:
System.out.println(Arrays.toString(numbers));Output:
[10, 20, 30]For multidimensional arrays:
System.out.println(Arrays.deepToString(matrix));53. Filling Arrays#
Suppose you need an array containing:
[-1, -1, -1, -1, -1]You could write a loop.
But Java provides:
Arrays.fill()Example:
import java.util.Arrays;
public class FillArrayExample {
public static void main(String[] args) {
int[] numbers = new int[5];
Arrays.fill(numbers, -1);
System.out.println(Arrays.toString(numbers));
}
}Output:
[-1, -1, -1, -1, -1]This is useful for:
- sentinel values
- initialization
- resetting buffers
- preparing algorithmic state
54. Important java.util.Arrays Methods#
At this point, you can see why the Arrays utility class exists.
Frequently used methods include:
| Method | Purpose |
|---|---|
Arrays.toString() | readable 1D representation |
Arrays.deepToString() | readable nested-array representation |
Arrays.sort() | sort elements |
Arrays.binarySearch() | binary search |
Arrays.equals() | compare 1D contents |
Arrays.deepEquals() | compare nested contents |
Arrays.fill() | fill elements |
Arrays.copyOf() | copy with requested length |
Arrays.copyOfRange() | copy a range |
55. Common Array Exceptions#
Arrays are simple but unforgiving around invalid indexes and null references.
Two major runtime problems are:
ArrayIndexOutOfBoundsExceptionNullPointerException
Other problems can occur while copying or storing incompatible reference types.
Let's understand the most important ones.
56. ArrayIndexOutOfBoundsException#
Example:
int[] numbers = {10, 20, 30};
System.out.println(numbers[3]);Array length:
3Valid indexes:
0, 1, 2Index 3 is invalid.
The program throws:
ArrayIndexOutOfBoundsExceptionThe same happens with negative indexes:
numbers[-1]Valid index rule#
0 <= index < array.length57. NullPointerException with Arrays#
Consider:
int[] numbers = null;
System.out.println(numbers.length);numbers does not refer to an array object.
Therefore accessing:
numbers.lengthcauses:
NullPointerExceptionSimilarly:
String[] names = new String[3];
System.out.println(names[0].length());names itself exists.
But:
names[0]is null.
Calling:
length()on that null reference causes NullPointerException.
These are two different null situations:
Array reference null
vs
Element inside array null58. ArrayStoreException#
A slightly more advanced array trap appears because Java arrays are covariant.
First, what does covariance mean here?
Java allows:
Object[] values = new String[3];because String is a subtype of Object.
This compiles.
Now consider:
values[0] = "Hello";Valid.
But:
values[1] = Integer.valueOf(10);The variable type is:
Object[]so this might look legal at compile time.
However, the actual array object is:
String[]A String[] cannot contain an Integer.
Therefore Java throws:
ArrayStoreExceptionExample:
public class ArrayStoreExample {
public static void main(String[] args) {
Object[] values = new String[2];
values[0] = "Java";
values[1] = Integer.valueOf(10);
}
}This is an important contrast between arrays and generic collections.
59. Negative Array Size#
This is invalid at runtime:
int[] numbers = new int[-5];It compiles because -5 is a valid integer expression.
But Java cannot construct an array with negative length.
Runtime result:
NegativeArraySizeException60. Zero-Length Arrays#
This is perfectly valid:
int[] numbers = new int[0];Then:
numbers.lengthis:
0There are simply no valid element indexes.
An empty array can be useful when a method wants to return:
no results
without returning null.
For many APIs, returning an empty array can make calling code simpler.
61. Arrays and Memory#
Suppose:
int[] numbers = new int[1_000_000];An array has contiguous logical indexed storage for its elements, and allocating a very large array requires sufficient heap memory.
The practical considerations include:
- array length
- element type
- object references
- nested arrays
- temporary copies
- sorting/copying operations
For primitive arrays, the array stores primitive values.
For object arrays, the array stores references, not the objects themselves.
Example:
Employee[] employees = new Employee[1000];This creates storage for 1,000 Employee references.
It does not automatically create 1,000 Employee objects.
62. Arrays Are Mutable#
Consider:
int[] numbers = {10, 20, 30};
numbers[0] = 999;The array content changes.
This mutability matters when:
- sharing arrays across methods
- exposing internal state
- working with multiple references
- processing data concurrently
If two parts of a program share the same mutable array, changes made by one can be visible to the other.
63. Defensive Copying#
Suppose a class accepts an array and stores the reference directly:
class Report {
private final int[] scores;
Report(int[] scores) {
this.scores = scores;
}
}Now external code still has that same array reference.
It can modify the array after constructing Report.
A safer approach when isolation is required is:
class Report {
private final int[] scores;
Report(int[] scores) {
this.scores = scores.clone();
}
}And if returning it:
public int[] getScores() {
return scores.clone();
}This is called defensive copying.
Important nuance:
For arrays of mutable objects, a shallow array clone may still share referenced objects.
64. Thread Safety#
Arrays themselves do not automatically make compound operations thread-safe.
Suppose several threads modify:
int[] counterssimultaneously.
The array provides indexed storage, but coordination between threads remains your responsibility.
Whether synchronization is needed depends on:
- operations being performed
- whether multiple threads mutate the same elements
- visibility requirements
- higher-level concurrency design
Do not assume:
It's an array, therefore access is thread-safe.
That conclusion is incorrect.
65. Array vs ArrayList#
Arrays often get compared with ArrayList.
Let's understand the decision, rather than memorizing definitions.
| Dimension | Array | ArrayList |
|---|---|---|
| Size | Fixed | Dynamically resizable |
| Primitive elements | Directly supported | Uses wrapper types for generics |
| Indexed access | Yes | Yes |
| Syntax | Language feature | Collection class |
| Length/size | .length | .size() |
| Add/remove operations | Manual | Built-in methods |
| Generic API integration | Limited | Strong |
| Low-level fixed structure | Excellent | Less direct |
| Dynamic application data | Less convenient | Often preferred |
Decision rule:
Fixed number of values?
Performance-sensitive primitive storage?
Low-level structured data?
→ Array may be appropriate
Dynamic number of application objects?
Frequent add/remove?
Need Collections APIs?
→ ArrayList is often more convenientArrays are not obsolete.
They remain fundamental and useful.
66. Array vs Individual Variables#
Use individual variables when values represent different concepts:
int age;
double salary;
String name;Do not create an array merely because multiple variables exist.
Use an array when values belong to the same conceptual sequence or group:
int[] monthlySales;
double[] temperatures;
String[] employeeNames;67. Correct vs Risky Array Design#
Risky#
int[] data = new int[10000];when only ten values may ever be needed and there is no clear reason to preallocate 10,000.
Why?
It may waste memory and communicate the wrong design intent.
Better when size is genuinely fixed#
int[] monthlySales = new int[12];Why?
The domain has exactly 12 months.
The fixed size matches the business requirement.
68. Learning Example vs Production Approach#
Learning example#
int[] marks = {80, 90, 75};
for (int mark : marks) {
System.out.println(mark);
}This is ideal for understanding arrays.
Typical production consideration#
In a real system, ask:
- Is the number of values fixed?
- Will the data be loaded dynamically?
- Is insertion/removal needed?
- Is primitive storage beneficial?
- Will external callers mutate the array?
- Do we need defensive copies?
- Is a collection API more maintainable?
- Do we need concurrency controls?
- Is a domain class more expressive?
Good production code starts with the requirement, not with loyalty to a particular data structure.
69. Common Mistakes#
Mistake 1 — Using <= array.length#
Mistake:
for (int i = 0; i <= numbers.length; i++)Why Developers Make It:
They think the last index equals the array length.
Why It Is Wrong:
Indexes run only to:
length - 1Possible Consequence:
ArrayIndexOutOfBoundsException.
Correct Approach:
for (int i = 0; i < numbers.length; i++)Debugging Signal:
Exception occurs near the end of traversal.
Interview Connection:
Classic off-by-one question.
Mistake 2 — Assuming Index Starts at 1#
Mistake:
numbers[1]when intending to access the first element.
Correct Rule:
First element:
numbers[0]Mistake 3 — Calling length()#
Wrong:
numbers.length()Correct:
numbers.lengthArrays expose a length field.
Mistake 4 — Expecting System.out.println(array) to Print Contents#
Risky expectation:
System.out.println(numbers);Preferred:
System.out.println(Arrays.toString(numbers));For nested arrays:
System.out.println(Arrays.deepToString(matrix));Mistake 5 — Believing Assignment Copies an Array#
Wrong assumption:
int[] second = first;means independent copy.
It does not.
Both references point to the same array.
Use a copy operation when independence is required.
Mistake 6 — Forgetting Object Array Elements Start as null#
Employee[] employees = new Employee[3];does not create three employees.
Initialize each object before dereferencing it.
Mistake 7 — Using Binary Search on Unsorted Input#
Risky:
int index = Arrays.binarySearch(numbers, target);without ensuring sorting compatible with the search order.
Correct mental model:
sort/order guarantee
↓
binary searchMistake 8 — Misreading copyOfRange()#
Remember:
from → inclusive
to → exclusiveMistake 9 — Modifying Enhanced-For Variable Instead of the Array Slot#
This does not replace primitive elements:
for (int n : numbers) {
n = 0;
}Use indexed assignment:
for (int i = 0; i < numbers.length; i++) {
numbers[i] = 0;
}Mistake 10 — Returning Internal Mutable Arrays Directly#
Potentially risky:
public int[] getScores() {
return scores;
}Caller can modify your internal state.
When isolation is required:
return scores.clone();Mistake 11 — Assuming clone() Creates Deep Copies of Objects#
Employee[] copy = original.clone();creates another array but shares the referenced Employee objects.
Mistake 12 — Assuming Every 2D Row Has Same Length#
Risky:
for (int j = 0; j < matrix[0].length; j++)for jagged data.
Preferred:
for (int j = 0; j < matrix[i].length; j++)70. Important Edge Cases#
Empty array#
int[] data = {};Valid.
Length:
0Null array#
int[] data = null;No array object exists.
One-element array#
int[] data = {10};Valid index:
0Duplicate values#
Arrays allow duplicates:
int[] values = {10, 10, 10};No uniqueness rule exists.
Negative values#
Perfectly valid as element values:
int[] values = {-10, -20};Only negative array length is invalid.
Null elements#
Reference arrays may contain null:
String[] names = {"Amit", null, "Neha"};Handle elements appropriately before dereferencing.
71. Complete Decision Rules#
Need multiple same-type fixed-count values?
→ Array
Need dynamic growth/shrink?
→ Consider ArrayList
Need every value only?
→ enhanced for
Need index/control/backward traversal?
→ traditional for
Need independent primitive array copy?
→ clone(), Arrays.copyOf(), System.arraycopy(), etc.
Need range copy?
→ Arrays.copyOfRange()
Need readable 1D printing?
→ Arrays.toString()
Need readable nested printing?
→ Arrays.deepToString()
Need 1D content comparison?
→ Arrays.equals()
Need nested content comparison?
→ Arrays.deepEquals()
Need sorting?
→ Arrays.sort()
Need binary searching?
→ sorted array + Arrays.binarySearch()
Need initialize all elements to same value?
→ Arrays.fill()
Need rows with different lengths?
→ jagged array72. Practical Example — Student Marks#
Let's combine several concepts.
Requirement:
Store student marks, calculate total, average, highest mark, and sort a copy without modifying the original order.
import java.util.Arrays;
public class StudentMarks {
public static void main(String[] args) {
int[] marks = {78, 92, 67, 88, 95};
int total = calculateTotal(marks);
double average = (double) total / marks.length;
int highest = findHighest(marks);
int[] sortedMarks = marks.clone();
Arrays.sort(sortedMarks);
System.out.println("Original: " + Arrays.toString(marks));
System.out.println("Sorted: " + Arrays.toString(sortedMarks));
System.out.println("Total: " + total);
System.out.println("Average: " + average);
System.out.println("Highest: " + highest);
}
static int calculateTotal(int[] marks) {
int total = 0;
for (int mark : marks) {
total += mark;
}
return total;
}
static int findHighest(int[] marks) {
int highest = marks[0];
for (int mark : marks) {
if (mark > highest) {
highest = mark;
}
}
return highest;
}
}Output:
Original: [78, 92, 67, 88, 95]
Sorted: [67, 78, 88, 92, 95]
Total: 420
Average: 84.0
Highest: 95Why clone before sorting?#
Because:
Arrays.sort(marks);would modify the original array.
We wanted both:
original order
and
sorted orderTherefore:
int[] sortedMarks = marks.clone();creates a separate primitive array.
73. Internal Execution Map#
When Java executes:
int[] numbers = new int[3];think:
Declare reference
↓
Evaluate new int[3]
↓
Allocate array object
↓
Initialize all elements to default int value 0
↓
Store reference in numbers
↓
numbers can access elements using indexes 0..2When Java executes:
int[] second = numbers;think:
Copy reference value
↓
Do NOT create new array
↓
Both variables reference same arrayWhen Java executes:
int[] copy = numbers.clone();think:
Create another array
↓
Copy array elements
↓
Primitive values independent
↓
Object references still shallow when elements are references74. Complete Chapter Revision#
One-line definitions#
Array: Fixed-size object storing elements of one declared type.
Index: Numeric position used to access an array element.
Length: Number of slots in an array.
Traversal: Processing array elements sequentially.
Jagged array: Multidimensional array whose inner arrays may have different lengths.
Shallow copy: New outer array containing copied references to the same underlying objects.
Core syntax#
Declaration:
int[] numbers;Creation:
numbers = new int[5];Declaration + creation:
int[] numbers = new int[5];Initialization:
int[] numbers = {10, 20, 30};Access:
numbers[0]Update:
numbers[1] = 50;Length:
numbers.lengthTraversal#
Traditional:
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}Enhanced:
for (int number : numbers) {
System.out.println(number);
}2D syntax#
int[][] matrix = {
{1, 2},
{3, 4}
};Access:
matrix[1][0]Important API memory map#
Print
→ Arrays.toString()
Print nested
→ Arrays.deepToString()
Sort
→ Arrays.sort()
Search sorted
→ Arrays.binarySearch()
Compare
→ Arrays.equals()
Compare nested
→ Arrays.deepEquals()
Fill
→ Arrays.fill()
Copy
→ Arrays.copyOf()
Copy range
→ Arrays.copyOfRange()
Low-level copy
→ System.arraycopy()75. If You Remember Only 10 Things#
- Arrays store multiple elements of one declared type.
- Array size is fixed after creation.
- First index is
0. - Last valid index is
length - 1. - Use
array.length, notarray.length(). - Array variables hold references to array objects.
second = firstdoes not copy the array.- Object-array elements initially contain
null. Arrays.equals()compares array contents;==compares references.Arrays.binarySearch()assumes appropriate sorted ordering.
76. Final Knowledge Map#
Java Arrays
│
├── Foundation
│ ├── What is an array?
│ ├── Why arrays exist
│ ├── Fixed size
│ ├── Same declared element type
│ └── Array as an object/reference
│
├── Basic Operations
│ ├── Declaration
│ ├── Creation
│ ├── Initialization
│ ├── Default values
│ ├── Index
│ ├── Access
│ ├── Update
│ └── length
│
├── Structure
│ ├── One-dimensional
│ ├── Two-dimensional
│ ├── Multidimensional
│ └── Jagged
│
├── Traversal
│ ├── Traditional for
│ └── Enhanced for
│
├── Methods
│ ├── Passing arrays
│ ├── Pass-by-value reference semantics
│ └── Returning arrays
│
├── Reference Arrays
│ ├── String[]
│ ├── Custom objects
│ ├── null elements
│ └── ArrayStoreException
│
├── Copying
│ ├── Assignment is not copying
│ ├── Manual copy
│ ├── clone()
│ ├── System.arraycopy()
│ ├── Arrays.copyOf()
│ ├── Arrays.copyOfRange()
│ └── Shallow vs deeper object copying
│
├── java.util.Arrays
│ ├── sort()
│ ├── binarySearch()
│ ├── equals()
│ ├── deepEquals()
│ ├── fill()
│ ├── toString()
│ └── deepToString()
│
├── Exceptions
│ ├── ArrayIndexOutOfBoundsException
│ ├── NullPointerException
│ ├── ArrayStoreException
│ └── NegativeArraySizeException
│
├── Production
│ ├── Defensive copying
│ ├── Memory
│ ├── Mutability
│ ├── Thread safety
│ └── Array vs ArrayList
│
└── Interview
├── Index boundaries
├── References
├── Pass-by-value
├── Copy semantics
├── Object arrays
├── Arrays utility methods
└── Edge cases