Now we’re going to shift gears a bit and return to the topic of arrays, considering them from the object point of view. At the end of Chapter 4, we mentioned that arrays have a place in the Java class hierarchy, but we didn’t give you any details. Now that we’ve discussed the object-oriented aspects of Java, we can give you the whole story.
Array classes live in a parallel Java class hierarchy under the
Object class. If a class is a direct
subclass of Object, an array class for
that base type also exists as a direct subclass of Object. Arrays of more derived classes are
subclasses of the corresponding array classes. For example, consider the
following class types:
classAnimal{...}classBirdextendsAnimal{...}classPenguinextendsBird{...}
Figure 6-8 illustrates the class
hierarchy for arrays of these classes. Arrays of the same dimension are
related to one another in the same manner as their base type classes. In
our example, Bird is a subclass of
Animal, which means that the Bird[] type is a subtype of Animal[]. In the same way a Bird object can be used in place of an Animal object, a Bird[] array can be assigned to a variable of
type Animal[]:
Animal[][]animals;Bird[][]birds=newBird[10][10];birds[0][0]=newBird();// make animals and birds reference the same array objectanimals=birds;observe(animals[0][0]);// processes Bird object
Because arrays are part of the class hierarchy, we can use instanceof to check the type of an array:
if(birdsinstanceofAnimal[][])// true
An array is a type of Object and
thus can be assigned to Object type
variables:
Objectobj=animals;
Because Java knows the actual type of all objects, you can also cast back if appropriate:
animals=(Animal[][])something;
Because arrays have the property that an array of one type
is assignable to an array of its supertype, it is possible to play games
with the compiler and try to trick it into storing the wrong kind of
object in an array. Java may not be able to check the types of all
objects that you place into arrays at compile time. In those cases, it’s
possible to receive an ArrayStoreException at runtime if you try to
assign the wrong type of object to an array element. For example:
String[]strings=newString[10];Object[]objects=strings;// alias String [] as Object []objects[0]=newDate();// Runtime ArrayStoreException!
Here, we have “aliased” a String
[] by assigning it to an Object
[]. By the third line, the compiler no longer knows the actual
type of array stored in the object’s variable and has no choice but to
let us try whatever we want. Of course, at runtime the VM realizes that
we are trying to put a Date object
into an array of Strings and throws
the ArrayStoreException for us. This type of problem
shouldn’t happen often for you in straightforward array use. We mention
it here because the concept will come up again when we talk about
generics in Chapter 8.