6.6 Arrays: Creation, Multidimensional Forms, and the Arrays Utility Class

Key Takeaways

  • Bracket placement changes meaning in multi-variable declarations: int[] x, y; declares two int arrays, while int p[], q; declares one int array and one plain int.
  • Array elements are default-initialized on allocation to 0, 0.0, the null character, false, or null; length is a final field rather than a method, and a negative size throws NegativeArraySizeException at run time.
  • Arrays are covariant, so assigning a String[] to an Object[] compiles but storing an incompatible element throws ArrayStoreException; generics are invariant and catch the same mistake at compile time.
  • Arrays.equals and Arrays.toString inspect only one level, so nested arrays require Arrays.deepEquals and Arrays.deepToString.
  • Arrays.asList returns a fixed-size view whose add and remove throw UnsupportedOperationException, and passing an int[] yields a one-element list rather than a list of three Integers.
Last updated: September 2026

Arrays: Creation, Multidimensional Forms, and the java.util.Arrays Utility Class

Oracle's Working with Arrays and Collections objective opens with the words "Create arrays, List, Set, Map and Deque collections, and add, remove, update, retrieve and sort their elements." Arrays are named first for a reason: they are the only container built into the language itself, they behave differently from every collection you have met so far, and 1Z0-830 uses them constantly as the vehicle for questions about declaration syntax, default values, covariance, and the Arrays helper methods.


1. Declaration Syntax and the Comma Trap

The square brackets may sit after the type or after the variable name. Both compile; only one is idiomatic.

int[] a;      // preferred
int b[];      // legal, C-style
int[] c[];    // legal - this is int[][]

The position matters enormously once you declare several variables in one statement:

int[] x, y;   // BOTH x and y are int[]
int p[], q;   // p is int[]; q is a plain int!
int[] r, s[]; // r is int[]; s is int[][]

Brackets are not part of the type in var declarations, and an array initializer alone gives the compiler nothing to infer from:

var t = new int[]{1, 2, 3};   // OK  -> int[]
// var u = {1, 2, 3};         // ERROR: array initializer needs an explicit target type

2. Creation and Default Element Values

There are three ways to build an array, and the brace-only shorthand works only in a declaration:

int[] sized    = new int[5];             // length 5, every element 0
int[] literal  = new int[]{10, 20, 30};  // anonymous array - usable anywhere
int[] shortcut = {10, 20, 30};           // ONLY valid in a declaration statement

int[] later;
// later = {1, 2, 3};                    // ERROR
later = new int[]{1, 2, 3};              // OK

Every element is initialized to the type's default the moment the array is allocated - arrays never contain "undefined" slots the way uninitialized local variables do:

Element typeDefault value
byte, short, int, long0
float, double0.0
charthe null character, escape \\u0000 (prints as a blank)
booleanfalse
Any reference typenull

length is a final field, not a method - the classic three-way confusion the exam loves:

int[] nums = new int[3];
nums.length;        // FIELD access, no parentheses
"Duke".length();    // String METHOD
List.of(1).size();  // Collection METHOD

Two runtime failures to recognize on sight:

int size = -1;
int[] bad = new int[size];   // compiles; throws NegativeArraySizeException
nums[3] = 9;                 // compiles; throws ArrayIndexOutOfBoundsException

3. Multidimensional and Jagged Arrays

Java has no true rectangular arrays - a two-dimensional array is an array whose elements are themselves array references.

int[][] grid = new int[3][4];   // fully allocated 3 x 4, all zeros
int[][] rows = new int[3][];    // 3 slots, each currently null
rows[0] = new int[2];
rows[1] = new int[5];           // rows may differ in length: a "jagged" array
// rows[2] stays null -> touching rows[2][0] throws NullPointerException

int[][] fromLiteral = {{1, 2}, {3, 4, 5}, {}};

Only the leftmost dimensions may be sized: new int[3][] is fine, but new int[][3] does not compile.


4. Covariance and ArrayStoreException

Arrays are covariant: String[] is a subtype of Object[]. Generics are invariant, which is why List<String> is not a List<Object> (section 6.2). Covariance means the compiler accepts assignments it cannot prove safe, so the check is deferred to run time.

Object[] objects = new String[2];   // compiles - covariance
objects[0] = "fine";                // OK
objects[1] = Integer.valueOf(42);   // compiles, but throws ArrayStoreException at run time

Arrays also inherit equals, hashCode, and toString straight from Object without overriding them:

int[] m = {1, 2};
int[] n = {1, 2};
System.out.println(m.equals(n));        // false - reference identity
System.out.println(m);                  // e.g. [I@6d06d69c
System.out.println(Arrays.toString(m)); // [1, 2]

clone() on an array is a shallow copy: cloning an int[][] duplicates the outer array but shares the row objects.


5. The java.util.Arrays Toolbox

MethodBehaviour worth memorizing
Arrays.toString(a)One-dimensional rendering; on a nested array it prints row references
Arrays.deepToString(a)Recursive rendering for nested arrays
Arrays.equals(a, b)Element-wise, but only one level deep
Arrays.deepEquals(a, b)Recursive comparison for nested arrays
Arrays.sort(a)Ascending natural order; the Comparator overload exists for object arrays only
Arrays.sort(a, from, to)Sorts the half-open range [from, to)
Arrays.binarySearch(a, key)Requires a sorted array; on unsorted input the result is undefined, not an exception
Arrays.fill(a, v)Overwrites every element (or a range) with v
Arrays.copyOf(a, n)Truncates, or pads with the element type's default
Arrays.copyOfRange(a, from, to)Half-open range copy
Arrays.asList(...)Fixed-size view backed by the array
Arrays.stream(a)IntStream/LongStream/DoubleStream for primitives, Stream<T> for objects
Arrays.compare / Arrays.mismatchLexicographic comparison, and the first differing index (-1 when equal)

When the key is absent, binarySearch returns -(insertion point) - 1, exactly as Collections.binarySearch does (section 6.5).

Arrays.asList - Two Separate Traps

List<String> view = Arrays.asList("a", "b", "c");
view.set(0, "z");    // OK - writes through to the backing array
// view.add("d");    // UnsupportedOperationException - fixed size
// view.remove(0);   // UnsupportedOperationException

Autoboxing does not reach inside an array, so a primitive array becomes a single element:

int[] primitives = {1, 2, 3};
System.out.println(Arrays.asList(primitives).size());   // 1  -> List<int[]>

Integer[] boxed = {1, 2, 3};
System.out.println(Arrays.asList(boxed).size());        // 3  -> List<Integer>

// Correct primitive conversion:
List<Integer> proper = Arrays.stream(primitives).boxed().toList();  // size 3

Copying Between Arrays

System.arraycopy(src, srcPos, dest, destPos, length) is the low-level primitive that copyOf and ArrayList growth are built on; going the other way, list.toArray(new String[0]) produces a correctly typed array.


6. Arrays Versus Collections

AspectArrayList
SizeFixed at creationGrows and shrinks
Holds primitivesYesNo - elements are boxed
Size querylength fieldsize() method
Type relationshipCovariant (ArrayStoreException)Invariant (compile-time safety)
Sequenced API (Java 21)Not applicablegetFirst(), reversed(), and friends

Reach for an array when the length is genuinely fixed and the elements are primitives; reach for a collection in almost every other case.

Loading diagram...
Array Declaration, Allocation, Covariance, and the Arrays Utility Traps
Test Your Knowledge

Given the declaration below, what are the types of p and q?

int p[], q;

A
B
C
D
Test Your Knowledge

What is the result of executing the following code?

Object[] values = new String[2];
values[0] = "Duke";
values[1] = Integer.valueOf(42);
System.out.println(values.length);

A
B
C
D
Test Your Knowledge

What does the following code print?

int[] primitives = {1, 2, 3};
Integer[] boxed = {1, 2, 3};
System.out.println(Arrays.asList(primitives).size() + " " + Arrays.asList(boxed).size());

A
B
C
D
Test Your Knowledge

Given the nested arrays below, what is printed?

int[][] left  = {{1, 2}, {3, 4}};
int[][] right = {{1, 2}, {3, 4}};
System.out.println(Arrays.equals(left, right) + " " + Arrays.deepEquals(left, right));

A
B
C
D