[4.1] Declare, instantiate, initialize, and use a one-dimensional array
[4.2] Declare, instantiate, initialize, and use a multidimensional array
In this section, I’ll cover declaration, allocation, and initialization of one-dimensional and multidimensional arrays. You’ll learn about the differences between arrays of primitive data types and arrays of objects.
An array is an object that stores a collection of values. The fact that an array itself is an object is often overlooked. I’ll reiterate: an array is an object itself; it stores references to the data it stores. Arrays can store two types of data:
An array of primitives stores a collection of values that constitute the primitive values themselves. (With primitives, there are no objects to reference.) An array of objects stores a collection of values, which are in fact heap-memory addresses or pointers. The addresses point to (reference) the object instances that your array is said to store, which means that object arrays store references (to objects) and primitive arrays store primitive values.
The members of an array are defined in contiguous (continuous) memory locations and hence offer improved access speed. (You should be able to quickly access all the students of a class if they all can be found next to each other.)
The following code creates an array of primitive data and an array of objects:
I’ll discuss the details of creating arrays shortly. The previous example shows one of the ways to create arrays. Figure 4.19 illustrates the arrays intArray and objArray. Unlike intArray, objArray stores references to String objects.
Arrays are objects and refer to a collection of primitive data types or other objects.
In Java, you can define one-dimensional and multidimensional arrays. A one-dimensional array is an object that refers to a collection of scalar values. A two-dimensional (or more) array is referred to as a multidimensional array. A two-dimensional array refers to a collection of objects in which each of the objects is a one-dimensional array. Similarly, a three-dimensional array refers to a collection of two-dimensional arrays, and so on. Figure 4.20 depicts a one-dimensional array and multidimensional arrays (two-dimensional and three-dimensional).
Note that multidimensional arrays may or may not contain the same number of elements in each row or column, as shown in the two-dimensional array in figure 4.20.
Creating an array involves three steps, as follows:
You can create an array by executing the previous steps using separate lines of code or you can combine these steps on the same line of code. Let’s start with the first approach: completing each step on a separate line of code.
An array declaration includes the array type and array variable, as shown in figure 4.21. The type of objects that an array can store depends on its type. An array type is followed by one or more empty pairs of square brackets [].
To declare an array, specify its type, followed by the name of the array variable. Here’s an example of declaring arrays of int and String values:
The number of bracket pairs indicates the depth of array nesting. Java doesn’t impose any theoretical limit on the level of array nesting. The square brackets can follow the array type or its name, as shown in figure 4.22.
In an array declaration, placing the square brackets next to the type (as in int[] or int[][]) is preferred because it makes the code easier to read by showing the array types in use.
The array declaration only creates a variable that refers to null, as shown in figure 4.23.
Because no elements of an array are created when it’s declared, it’s invalid to define the size of an array with its declaration. The following code won’t compile:
An array type can be any of the following:
We declared an array of an int primitive type and a concrete class String previously. I’ll discuss some complex examples with abstract classes and interfaces in section 4.3.7.
Arrays can be of any data type other than null.
As the name suggests, array allocation will allocate memory for the elements of an array. When you allocate memory for an array, you should specify its dimensions, such as the number of elements the array should store. Note that the size of an array can’t expand or reduce once it is allocated. Here are a few examples:
Because an array is an object, it’s allocated using the keyword new, followed by the type of value that it stores, and then its size. The code won’t compile if you don’t specify the size of the array or if you place the array size on the left of the = sign, as follows:
The size of the array must evaluate to an int value. You can’t create an array with its size specified as a floating-point number. The following line of code won’t compile:
Java accepts an expression to specify the size of an array, as long as it evaluates to an int value. The following are valid array allocations:
Let’s allocate the multidimensional array multiArr, as follows:
You can also allocate the multidimensional array multiArr by defining size in only the first square brackets:
It’s interesting to note the difference between what happens when the multidimensional array multiArr is allocated by defining sizes for a single dimension or for both of its dimensions. This difference is shown in figure 4.24.
You can’t allocate a multidimensional array as follows:
won’t compile because there’s a mismatch in the number of square brackets on both sides of the assignment operator (=). The compiler required [][] on the right side of the assignment operator, but it finds only []. won’t compile because you can’t allocate a multidimensional array without including a size in the first square bracket and defining a size in the second square bracket.
Once allocated, the array elements store their default values. For arrays that store objects, all the allocated array elements store null. For arrays that store primitive values, the default values depend on the exact data types stored by them.
Once allocated, all the array elements store their default values. Elements in an array that store objects default to null. Elements of an array that store primitive data types store 0 for integer types (byte, short, int, long); 0.0 for decimal types (float and double); false for boolean; or u0000 for char data.
You can initialize an array as follows:
In the preceding code, uses a for loop to initialize the array intArray with the required values. initializes the individual array elements without using a for loop. Note that all array objects use their public immutable field length to access their array size.
Similarly, a String array can be declared, allocated, and initialized as follows:
When you initialize a two-dimensional array, you can use nested for loops to initialize its array elements. Also notice that to access an element in a two-dimensional array, you should use two array position values, as follows:
What happens when you try to access a nonexistent array index position? The following code creates an array of size 2 but tries to access its array element at index 3:
The previous code will throw a runtime exception, ArrayIndexOutOfBounds-Exception. For an array of size 2, the only valid index positions are 0 and 1. All the rest of the array index positions will throw the exception ArrayIndexOutOfBoundsException at runtime.
Don’t worry if you can’t immediately absorb all the information related to exceptions here. Exceptions are covered in detail in chapter 7.
The Java compiler doesn’t check the range of the index positions at which you try to access an array element. You may be surprised to learn that the following line of code will compile successfully even though it uses a negative array index value:
Although the previous code compiles successfully, it will throw the exception Array-IndexOutOfBoundsException at runtime. Code to access an array element will fail to compile if you don’t pass it a char, byte, short, or int data type (wrapper classes are not on this exam, and I don’t include them in this discussion):
Code to access an array index will throw a runtime exception if you pass it an invalid array index value. Code to access an array index will fail to compile if you don’t use a char, byte, short, or int.
Also, you can’t remove array positions. For an array of objects, you can set a position to the value null, but it doesn’t remove the array position:
creates an array of String and initializes it with four String values. sets the value at array index 2 to null. iterates over all the array elements. As shown in the following output, four (not three) values are printed:
Autumn Summer null Winter
You can combine all the previously mentioned steps of array declaration, allocation, and initialization into one step, as follows:
int intArray[] = {0, 1}; String[] strArray = {"Summer", "Winter"}; int multiArray[][] = { {0, 1}, {3, 4, 5} };
All the previous steps of array declaration, allocation, and initialization can be combined in the following way, as well:
int intArray2[] = new int[]{0, 1}; String[] strArray2 = new String[]{"Summer", "Winter"}; int multiArray2[][] = new int[][]{ {0, 1}, {3, 4, 5}};
Unlike the first approach, the preceding code uses the keyword new to initialize an array.
If you try to specify the size of an array with the preceding approach, the code won’t compile. Here are a few examples:
int intArray2[] = new int[2]{0, 1}; String[] strArray2 = new String[2]{"Summer", "Winter"}; int multiArray2[][] = new int[2][]{ {0, 1}, {3, 4, 5}};
When you combine an array declaration, allocation, and initialization in a single step, you can’t specify the size of the array. The size of the array is calculated by the number of values that are assigned to the array.
Another important point to note is that if you declare and initialize an array using two separate lines of code, you’ll use the keyword new to initialize the values. The following lines of code are correct:
int intArray[]; intArray = new int[]{0, 1};
But you can’t miss the keyword new and initialize your array as follows:
int intArray[]; intArray = {0, 1};
At the beginning of this section, I mentioned that a multidimensional array can be asymmetrical. An array can define a different number of columns for each of its rows.
The following example is an asymmetrical two-dimensional array:
String multiStrArr[][] = new String[][]{ {"A", "B"}, null, {"Jan", "Feb", "Mar"}, };
Figure 4.25 shows this asymmetrical array.
As you might have noticed, multiStrArr[1] refers to a null value. An attempt to access any element of this array, such as multiStrArr[1][0], will throw an exception. This brings us to the next Twist in the Tale exercise (answers are in the appendix).
Modify some of the code used in the previous example as follows:
Line1> String multiStrArr[][] = new String[][]{ Line2> {"A", "B"}, Line3> null, Line4> {"Jan", "Feb", null}, Line5> };
Which of the following individual options are true for the previous code?
In the section on array declaration, I mentioned that the type of an array can also be an interface or an abstract class. What values do elements of these arrays store? Let’s look at some examples.
If the type of an array is an interface, its elements are either null or objects that implement the relevant interface type. For example, for the interface MyInterface, the array interfaceArray can store references to objects of either the class MyClass1 or MyClass2:
interface MyInterface {} class MyClass1 implements MyInterface {} class MyClass2 implements MyInterface {} class Test { MyInterface[] interfaceArray = new MyInterface[] { new MyClass1(), null, new MyClass2() }; }
If the type of an array is an abstract class, its elements are either null or objects of concrete classes that extend the relevant abstract class:
Next, I’ll discuss a special case in which the type of an array is Object.
Because all classes extend the class java.lang.Object, elements of an array whose type is java.lang.Object can refer to any object. Here’s an example:
is valid code. Because an array is an object, the element of the array of java.lang.Object can refer to another array. Figure 4.26 illustrates the previously created array, objArray.
18.188.61.81