arrays
fixed-size boxes in a row. 2d arrays are arrays of arrays (literally).
- chapter
- chapter 02.08
- reading time
- 6 min read
an array is a fixed-size row of slots, all of one type, numbered from 0. it's an object on the heap, so the variable holds a reference to it. you can't grow one; you make a new one and copy. and a 2d array is literally an array of arrays, which is why its rows can have different lengths.
the picture
a row of numbered lockers, all the same size, bolted together. you get to pick how many when you build it, and that number is final. locker numbers start at 0, so a row of 5 goes from 0 to 4.
int[] scores = {90, 72, 85};
String[] names = {"ada", "linus"};int[] holds the ints themselves. a String[] holds references, one arrow per slot, because strings are objects too.making and using one
void main() {
int[] a = {3, 1, 4, 1, 5};
IO.println(a.length + " " + a[0] + " " + a[a.length - 1]);
IO.println(Arrays.toString(new int[3]) + " " + Arrays.toString(new String[2]) + " " + Arrays.toString(new boolean[2]));
}5 3 5 [0, 0, 0] [null, null] [false, false]
{3, 1, 4}builds and fills one in one go.new int[5]makes an empty one of length 5.- an empty array isn't empty, it's zeroed:
0for numbers,falsefor booleans,nullfor references. (fields get the same defaults; local variables don't.) a.lengthis a field, no parentheses (unlikeString.length(), a classic mixup).- the last element is
a[a.length - 1].a[a.length]is one past the end.
five ints in a row. pick an index to read, or run one of the Arrays helpers.
Arrays helpers. watch the object number: sort and fill change the array in place, but copyOf hands you a brand new array.java checks every index, every time. read past the end and you get an exception, never somebody else's memory (that's a whole class of C security bugs that can't happen here):
void main() {
int[] a = new int[5];
IO.println("reading a[5]...");
IO.println(a[5]);
}reading a[5]... Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
printing and comparing
void main() {
int[] a = {3, 1, 4, 1, 5};
int[] b = Arrays.copyOf(a, 7);
Arrays.sort(a);
IO.println(Arrays.toString(a) + " " + Arrays.toString(b));
int[] d = {1, 2, 3};
int[] e = {1, 2, 3};
IO.println((d == e) + " " + d.equals(e) + " " + Arrays.equals(d, e));
}[1, 1, 3, 4, 5] [3, 1, 4, 1, 5, 0, 0] false false true
two traps in there. println(a) on an array prints something like [I@5a4041cc (the type code for "int array", an @, and a hash), never the contents: use Arrays.toString. and both == and equals on arrays ask "same object?", so two arrays with identical contents aren't "equal". use Arrays.equals.
int[] a = {1, 2, 3};
for (int x : a) {
x *= 2;
}
IO.println(Arrays.toString(a));2d arrays are arrays of arrays
java has no real grid type. int[][] means "an array whose elements are int[]s". the outer array holds references, and each row is a separate array object:
int[][] grid = new int[3][4];
grid[1][2] = 9;grid[1][2] means: follow slot 1 of the outer array, then read slot 2 of that row.since each row is its own array, the rows don't have to be the same length. leave the second size out (new int[3][]) and you get the outer array only, rows to be filled in later:
- 1void main() {
- 2 int[][] tri = new int[3][];
- 3 tri[0] = new int[] {1};
- 4 tri[1] = new int[] {1, 1};
- 5 tri[2] = new int[] {1, 2, 1};
- 6 int[] row = tri[2];
- 7 row[1] = 9;
- 8 IO.println(tri[2][1]);
- 9}
·main starts.
row and tri[2] become two arrows to the same row, so a write through one shows up through the other.Arrays.deepToString(grid) prints nested arrays ([[0, 0, 0, 0], [0, 0, 9, 0], [0, 0, 0, 0]]), since plain toString would print the rows' [I@... addresses.
arrays are covariant, and it can blow up at runtime+
a String[] is a kind of Object[], so this compiles:
Object[] o = new String[1];
o[0] = 42;and then throws ArrayStoreException: java.lang.Integer when it runs, because the array remembers it was created as a String[] and checks every store. that runtime check is why arrays and generics don't mix well, and why List<String> is deliberately not a List<Object>. the whole story is in arrays, varargs and other limits.
- an array is a fixed-size, zero-indexed object. the variable holds a reference.
- new arrays are zeroed: 0, false, null.
- every index is checked. out of range throws
ArrayIndexOutOfBoundsException. - print with
Arrays.toString, compare withArrays.equals.==andequalsmean "same object". int[][]is an array of row arrays. rows can differ in length.