Do you know Java: Arrays as Generic Containers


We can assign different type of elements to an array even the operation is accepted in compile-time, that raises error in run-time.

Sometimes Java is tricky, even it has static type system, we can assign different type of elements to an array, which is accepted in compile time, even array contains different type than the types of the element.

Covariance

Let S <: T mean that S is subtype of T and covariant is S <: T => S' <: T'.

In Java, array subtyping is covariant, that means that type S[] is considered to be a subtype of T[] whenever S is a subtype of T. Hence, S <: T => S[] <: T[].

How it works

Since, String <: Object, then String[] <: Object[].

String fruit = "apple";
Object tool = fruit;
Object[] tools = {"hammer", "screwdriver"};
String[] fruits = {"apple", "plum"};

tools[1] = Integer.MAX_VALUE;  // tools: type: Object[], value: {"hammer", Integer(1)}

tools = fruits;  // tools: type: String[], value: {"apple", "plum"}

Here, tools is a reference to an array that contains String objects. Since the static type of the elements in the array is Object, we can easily assign new element to the array which type is either Object or one of its subtype.

Object[] tools = {"hammer", "screwdriver"};
String[] fruits = {"apple", "plum"};

tools[1] = Integer.MAX_VALUE;  // tools: type: Object[], value: {"hammer", Integer(1)}

tools = fruits;  // tools: type: String[], value: {"apple", "plum"}

tools[1] = Integer.MAX_VALUE;
Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer
  • Though, static type is Object[], its dynamic type is String[]
  • No compile time exception! Exception occured in runtime! It is way too late!

Unfortunately, arrays as containers are not type-safe, and we, developers, have to take the responsibility to make sure that read and write operations are type-safe. It does not support rich functionality like List, Set, or Queue do, and we are responsible to extend that if number of elements reach the capacity.

Arrays as generic containers are not type-safe, and do not support type-safe read and write operations in compie-time.

Code can be found: https://github.com/torokmark/do-you-know-java