/* Like C++, Java must live with its own mistakes. In order of pain magnitude: KILOHURTS: Arrays were allowed to be covariant, Object[] A = new String[10]; This was needed to implement generic algorithms over arrays, as in void quicksort(Object[] A): must be able to pass it a String[] But then A[0] = 1.23; // will compile. MEGAHURTS: Generics where implemented using type erasure. Probably management separeted the JVM team from the high-level language team, and the language team were not allowed to make modifications to the JVM. Using arrays together with generics is a nightmare. Also inefficient. GIGAHURTS: Over-reliance on the null pointer. */ import java.util.ArrayList; public class pain { // static T x; // you're really declaring a static Object x for every // instantiation of T. T[] A; T[] B; ArrayList[] D; ArrayList AL = new ArrayList(); // this is fine! void garbage() { //T[] A = new T[10]; // generic array creationg // var A = new java.util.ArrayList[10]; /* Why didn't the above lines compile? because arrays, as the original "generic" data structure, did not use type erasure. That is, a String[] and an int[] are distinguishable from eachother at runtime as well as at compile-time. One cannot cast a String[] to an Integer[] at runtime. arrays must carry this precise type information at runtime. */ // But then why is this allowed, albeit with a warning: A = (T[]) new Object[10]; B = (T[]) new String[10]; D = (ArrayList[]) new ArrayList[10]; // why are these operations unsafe? because the type is // dynamically, not statically attached to the arrays, the compiler // is asked to trust that the dynamic type of B is compatible // with whatever T is. // Java (and C#) allowed arrays to be covariant, so you can // instantiate an Object[] with a String[]. }// static void this_trash_compiles() { pain M = new pain(); // so what "type" is the array B created in the garbage function? M.garbage(); M.A[0] = 1.2; // M.B[0] = "abc"; // doesn't compile because of static typing M.B[0] = 3.4; // compiles but runtime error M.B[1] = (Double)(Object)"abc"; } public static void main(String[] args) { this_trash_compiles(); } } /* Warning is given for type casting because type erasure means there's no way to type check array at runtime - because the type attached to T[] is not the correct type, but Object (or anything else). But there's a chance it might be ok. If T was instantiated by supertype of both Object and String. But it must allow it because there's no other way to use arrays in a generic setting. */