int[] numbers = new int[5]; // all elements default to 0
numbers[0] = 10;
numbers[1] = 20;
int[] literal = {1, 2, 3, 4, 5}; // initializer syntax
System.out.println(literal[2]); // prints 3
System.out.println(literal.length); // prints 5, note: .length is a field, not a method
Topics
36
Annotations
Arrays & Multidimensional Arrays
Build Tools: Maven & Gradle
Class Loading & Bytecode Verification
Collections Framework
Concurrency & Threads
Design Patterns in Java
Enums
equals(), hashCode() & toString() Contracts
Exceptions
Functional Interfaces & Method References
Garbage Collection
Generics
I/O & NIO
Inner Classes & Anonymous Classes
Interfaces & Abstract Classes
Java Date & Time API (java.time)
Java Fundamentals: Syntax, Data Types & Operators
Java Networking & HTTP Client
Java Platform Module System (JPMS)
JDBC & Database Connectivity
JVM, JRE & Memory
Logging in Java (java.util.logging, SLF4J, Log4j)
Object Cloning & Copy Semantics
OOP & Classes
Optional & Null Safety
Pattern Matching & Switch Expressions
Records & Sealed Classes
Reflection API
Regular Expressions in Java
Serialization & Deserialization
Static & Instance Initialization Blocks
Streams & Lambdas
String Handling, StringBuilder & Immutability
Unit Testing with JUnit & Mockito
Varargs, Autoboxing & Unboxing
Arrays & Multidimensional Arrays
15 questions found
An array is declared with a type followed by square brackets (int[] arr), instantiated with new specifying its fixed size (new int[5]) or using an initializer literal ({1, 2, 3}), and accessed/modified via zero-based indexing (arr[0]) -- once created, an array's length is fixed and immutable for its lifetime, unlike a resizable collection like ArrayList.
Real-world example
A fixed-size lookup table mapping day-of-week integers (0-6) to day names is implemented as a simple String array, appropriate since the collection's size is known and fixed at compile time and never needs to grow or shrink.
Collections Framework;Java Fundamentals: Syntax
Data Types & Operators
How do multidimensional arrays work in Java, and how do they differ from truly rectangular arrays in languages like C?
IntermediateJava doesn't have true multidimensional arrays in the C sense; a 2D array (int[][]) is actually an array of arrays, where each row is an independently allocated one-dimensional array object -- this means rows can have different lengths (a "jagged" array), unlike a genuinely rectangular structure, and each row must be individually instantiated or accessed via nested indexing, with memory layout reflecting this array-of-arrays structure rather than one contiguous rectangular block.
int[][] matrix = new int[3][4]; // 3 rows, each with 4 columns (rectangular)
matrix[1][2] = 99;
int[][] jagged = new int[3][]; // 3 rows, columns not yet specified
jagged[0] = new int[2];
jagged[1] = new int[5]; // different length than row 0 -- legal, since it's an array of arrays
jagged[2] = new int[1];
Real-world example
A program modeling a triangular data structure (like Pascal's triangle, where each row has one more element than the previous) uses a jagged array where each row is deliberately allocated with a different length, taking advantage of Java arrays not being required to be rectangular.
Java Fundamentals: Syntax
Data Types & Operators;Generics
How does Java implement covariant array typing, and why is this considered a design flaw that can lead to runtime ArrayStoreException?
AdvancedJava arrays are covariant, meaning Object[] arr = new String[3] is legal (a String[] reference can be assigned to an Object[] variable) since arrays retain their actual runtime component type -- but this creates a loophole where code operating on the Object[] reference can attempt to insert an incompatible type at runtime (arr[0] = Integer.valueOf(1)), which the compiler cannot catch statically and instead throws ArrayStoreException only when that specific line actually executes, illustrating why generics deliberately chose invariance instead to catch such errors at compile time.
Object[] arr = new String[3]; // legal due to covariance
arr[0] = "hello"; // fine, actual runtime type is String[]
arr[1] = Integer.valueOf(42); // compiles fine (Object accepts Integer)... but throws ArrayStoreException at RUNTIME
Real-world example
A library method accepting an Object[] parameter unknowingly receives a String[] and attempts to insert a non-String object into it, causing a production ArrayStoreException that a compile-time type system (like Java Generics' intentional invariance) would have caught much earlier during development instead.
Generics;Exceptions
What utility methods does java.util.Arrays provide for common array operations like sorting, searching, filling, and comparing?
IntermediateArrays provides static utility methods including sort() (in-place sorting, dual-pivot quicksort for primitives, TimSort for objects), binarySearch() (requires a pre-sorted array), fill() (populate all elements with one value), copyOf()/copyOfRange() (create a resized copy), equals()/deepEquals() (element-wise comparison, deepEquals needed for nested arrays), and asList() (a fixed-size List view backed by the array) -- these cover the vast majority of common array manipulation needs without hand-writing loops.
int[] nums = {5, 2, 8, 1, 9};
Arrays.sort(nums); // {1, 2, 5, 8, 9}
int index = Arrays.binarySearch(nums, 8); // 3
int[] copy = Arrays.copyOf(nums, 3); // {1, 2, 5}
int[][] matrix1 = {{1,2},{3,4}};
int[][] matrix2 = {{1,2},{3,4}};
System.out.println(Arrays.equals(matrix1, matrix2)); // false -- compares references of inner arrays
System.out.println(Arrays.deepEquals(matrix1, matrix2)); // true -- recursively compares contents
Real-world example
A data-processing utility sorts a large primitive int array using Arrays.sort() (leveraging its highly optimized dual-pivot quicksort implementation) rather than converting to a boxed Integer collection just to use Collections.sort(), avoiding unnecessary boxing overhead for a purely numeric workload.
Collections Framework;Generics
How would you efficiently copy, resize, or merge large arrays in Java, and what are the performance trade-offs between System.arraycopy(), Arrays.copyOf(), and manual loops?
AdvancedSystem.arraycopy() is a native method performing highly optimized bulk memory copying (often using intrinsic CPU instructions), generally the fastest option for copying array ranges; Arrays.copyOf() internally calls System.arraycopy() but adds the convenience of allocating the destination array for you, at the cost of one extra layer of indirection; a manual element-by-element loop is almost always slower than either since it can't benefit from the same low-level bulk-copy optimizations, and should generally be avoided for simple copy operations in favor of the built-in methods.
int[] source = {1, 2, 3, 4, 5};
// Fastest for a pre-allocated destination
int[] dest = new int[5];
System.arraycopy(source, 0, dest, 0, source.length);
// Convenient, internally uses System.arraycopy
int[] resized = Arrays.copyOf(source, 10); // pads with zeros
// Merging two arrays efficiently
int[] merged = new int[source.length + dest.length];
System.arraycopy(source, 0, merged, 0, source.length);
System.arraycopy(dest, 0, merged, source.length, dest.length);
Real-world example
A high-throughput data pipeline processing large numeric arrays uses System.arraycopy() directly for merging and resizing buffers, having profiled that this measurably outperforms a naive manual copy loop at the scale the pipeline operates, since arraycopy benefits from JIT intrinsics mapping directly to optimized native memory operations.
Concurrency & Threads;Garbage Collection
How do you convert between an array and a List (ArrayList) in both directions, and what pitfalls exist with Arrays.asList()?
IntermediateArrays.asList(array) returns a fixed-size List backed directly by the original array (not a true resizable ArrayList -- calling add()/remove() throws UnsupportedOperationException, and mutating the array is reflected in the list view and vice versa); to get a genuinely independent, resizable list, wrap it in new ArrayList<>(Arrays.asList(array)); converting back from a List to an array uses list.toArray(new String[0]) (or the newer list.toArray(String[]::new)).
Integer[] arr = {1, 2, 3};
List<Integer> fixedView = Arrays.asList(arr); // backed by arr, fixed-size
// fixedView.add(4); // throws UnsupportedOperationException!
List<Integer> resizable = new ArrayList<>(Arrays.asList(arr)); // truly independent, resizable copy
resizable.add(4); // works fine
Integer[] backToArray = resizable.toArray(new Integer[0]);
Real-world example
A developer's attempt to call .add() on a list obtained directly from Arrays.asList() throws an unexpected UnsupportedOperationException in production, a common pitfall traced to Arrays.asList() returning a fixed-size view rather than a genuine resizable ArrayList.
Collections Framework;Generics
How would you implement an efficient in-place algorithm on a 2D array, such as rotating a matrix 90 degrees, while minimizing extra memory allocation?
AdvancedAn in-place rotation can be achieved through a combination of transposing the matrix (swapping matrix[i][j] with matrix[j][i] across the diagonal) followed by reversing each row (or column, depending on rotation direction), avoiding the need to allocate an entirely new matrix -- this two-step decomposition is a classic technique that reduces an seemingly complex 2D transformation into two simpler, well-understood O(n²) operations performed directly on the existing array structure.
public static void rotate90Clockwise(int[][] matrix) {
int n = matrix.length;
// Step 1: transpose in place
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// Step 2: reverse each row
for (int[] row : matrix) {
for (int left = 0, right = row.length - 1; left < right; left++, right--) {
int temp = row[left];
row[left] = row[right];
row[right] = temp;
}
}
}
Real-world example
An image-processing utility rotating a pixel matrix representing a small icon uses the transpose-then-reverse in-place technique to avoid allocating a second full-size matrix, meaningful for memory-constrained environments processing many images where allocation overhead would otherwise add up significantly.
Diagnostics & Performance;Garbage Collection
How does Java handle array bounds checking, and what exception is thrown when accessing an invalid index?
IntermediateEvery array access in Java is automatically bounds-checked by the JVM at runtime, throwing ArrayIndexOutOfBoundsException (an unchecked RuntimeException) if the index is negative or greater than or equal to the array's length -- this automatic checking prevents the memory-corruption vulnerabilities common in languages like C that allow unchecked buffer access, at the cost of a small but generally negligible runtime overhead for each array access, though modern JIT compilers can often eliminate redundant bounds checks through optimization when they can statically prove an index is always safe.
int[] arr = {1, 2, 3};
try {
System.out.println(arr[5]); // throws ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid index: " + e.getMessage());
}
Real-world example
A parsing routine iterating a fixed-size array with an off-by-one loop bound (using <= instead of <) is caught immediately in testing by the resulting ArrayIndexOutOfBoundsException, illustrating how Java's automatic bounds checking surfaces this class of bug loudly and immediately rather than causing silent memory corruption as it might in an unmanaged language.
Exceptions;Diagnostics & Performance
How would you implement a custom, resizable dynamic array (similar to ArrayList's internal mechanism) from scratch using a raw Java array, including the amortized doubling growth strategy?
AdvancedA dynamic array wraps a fixed-size backing array along with a separate size counter (tracking logically used elements, distinct from the backing array's full capacity); when an add operation would exceed capacity, allocate a new backing array (conventionally double the current capacity) and copy existing elements over via System.arraycopy() -- this doubling strategy gives amortized O(1) add performance, since the expensive resize-and-copy operation happens increasingly rarely relative to the number of cheap O(1) adds, exactly matching how java.util.ArrayList is implemented internally.
public class SimpleDynamicArray<T> {
private Object[] data = new Object[10];
private int size = 0;
public void add(T element) {
if (size == data.length) {
data = Arrays.copyOf(data, data.length * 2); // double capacity
}
data[size++] = element;
}
@SuppressWarnings("unchecked")
public T get(int index) {
if (index < 0 || index >= size) throw new IndexOutOfBoundsException();
return (T) data[index];
}
public int size() { return size; }
}
Real-world example
An educational exercise reimplements a simplified version of ArrayList from scratch to demonstrate the amortized doubling growth strategy, showing why ArrayList's add() operation is described as amortized O(1) despite an occasional individual call actually costing O(n) during a resize event.
Collections Framework;Generics
How do you correctly iterate a 2D array using both traditional indexed for-loops and the enhanced for-each loop, and when is each approach preferable?
IntermediateThe enhanced for-each loop (for (int[] row : matrix) { for (int value : row) { ... } }) is more concise and less error-prone for simple read-only traversal, avoiding index-related bugs entirely, but doesn't give you direct access to the current index (needed if you must modify elements in place, or need to know row/column position for logic); the traditional indexed loop is required whenever you need to mutate elements, need the index for other computation, or need to iterate multiple related arrays in lockstep using a shared index.
int[][] matrix = {{1,2,3},{4,5,6}};
// for-each: simpler for read-only traversal
for (int[] row : matrix) {
for (int value : row) {
System.out.print(value + " ");
}
}
// indexed: needed when mutating in place or requiring the index
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
matrix[i][j] *= 2; // requires index-based access to mutate
}
}
Real-world example
A matrix-doubling utility uses an indexed loop specifically because it needs to write back into each cell (matrix[i][j] *= 2), whereas a separate read-only matrix-printing utility uses the simpler for-each syntax since it never needs to mutate or track explicit indices.
Java Fundamentals: Syntax
Data Types & Operators;Generics
Showing 1–10 of 15