T [] aa = (T[]) new Object[2];
Because that line is broken. Your compiler warned you when you tried to compile it. As a general rule, if you get a compiler warning you do not understand, then do something else - java compiler warnings are best treated as: "Your code is completely broken and this is not going to work, but for the benefit of e.g. trying to start this application up because you want to test a completely different part of it, we'll just slap this broken stuff in a class file so you can move on, for now. Do not under any circumstances publish this to production until you fully understand this warning first."
In java, generics is a 100% compile-time show: Generics are compiler-checked documentation. At runtime, generics are mostly erased, and the few places where they remain, they are 'comments' as far as the runtime is concerned. The verifier and the runtime system never does any checks, ever. If javac allows it, the generics are now done being useful.
This in sharp contrast to arrays: Arrays are their own object and they DO know their 'component type'. Also, the compiler doesn't do all that much checking on them, but the runtime DOES. If you use some classfile hackery to put an Integer in a List<String>, the runtime will let you. However, you cannot use any amount of hackery to put an Integer in a String[]. It just won't work - you end up with an ArrayStoreException instead.
Because arrays actually know their type, at runtime, Integer[] and Object[] are different types (whereas at runtime, a List is just a List - the runtime doesn't know what generics are).
T is Integer, and that variable is of type T[], therefore, it is Integer[], therefore, any interactions with aa get you an implicit cast to Integer[]. This is 100% analogous to this code:
List<String> list = new ArrayList<String>();
List raw = list; // legal, but gets you a warning.
raw.add(5);
System.out.println(list.get(0));
You can compile it. If you run it, the last line throws ClassCastException which is weird, there is no cast there at all! Ah, but there is. Because the compiler rewrote that for you, into this code (and remember, the runtime does not know generics, which is why it is rewritten like this):
List list = new ArrayList();
List raw = list;
raw.add(Integer.valueOf(5));
String $v = (String) list.get(0);
System.out.println($v);
You'd think: Wait, why cast it? There is a System.out.println(Object) variant? But, that's just the rules. Java will immediately cast that because it can, after all, list is a List<String> which means its get(int idx) method can be assumed to always return strings, so java will cast it as soon as possible even if not needed.
The exact same thing happens in your code: It sees T[], where T is bound to Integer, so, aa is cast to Integer[] even if it wasn't needed. This cast fails at runtime because an object created as new Object[2] is clearly not an Integer[]. After all, I can invoke:
Integer[] x = ...;
System.out.println(x.getClass().getComponentType());
and this code is guaranteed to print java.lang.Integer. If I can write code so that java.lang.Object is printed, that would be broken, and yet that is exactly what would happen.
So how do I fix it?
Do not, ever, write T[]. It's as simple as that.
Arrays are low-level constructs you shouldn't be using, especially if the component type is non-primitive. If you MUST use them, then they should be relegated to internal implementation details, hidden behind a nicer API.
Do the casting in those wrappers.
This is precisely how ArrayList works. ArrayList has an array inside that holds your list elements (hence the name ArrayList). That is defined as Object[] storage = new Object[...];. Not T[] storage = (T[]) new Object[..]. Then, the get method of ArrayList does the casting:
public T get(int idx) {
// check if idx is within 0-size()...
return (T) storage[idx];
}
This cast does nothing (javac emits a warning that it has no idea what T might be and the runtime doesn't either, so nobody can check this), but this will all work at runtime (obviously: ArrayList works fine).
You need to do the same thing, and hide that array, if you must use it. Or better yet, don't do any of this stuff and use List<T> instead. Arrays of non-primitive types are a blight: If you use them, you better have an excellent reason for it, and hide it as much as possible.