As i understood, compiler mark type parametr T in a non static context as known and hence we can instanciate ArrayList.
No. Even in non-static context, compiler doesn't know what type T
denotes. The reason why new ArrayList<T>();
works is, compiler knows that ArrayList<E>
has a 0-arg constructor. The type parameter T
will just be replaced by actual type argument. And it can be any type. And since you can create an ArrayList
of anytype, that is fine.
But new operator requires a specific type. Type parametr T is specific i non static context. Where i've wrong reasoning?
In case of new T();
, again since the compiler doesn't know what type T
is, hence it doesn't know, whether there is any accessible 0-arg constructor of T
or not. Consider a class as below:
class Test {
private int value;
public Test(int value) { this.value = value; }
}
And then you instantiate your generic class as:
MyClass<Test> obj = new MyClass<Test>();
Now, assume that compiler allows new T();
, then for this instantiation, it is like doing - new Test();
. But there is no 0-arg constructor in Test
. So, how would you expect that code to behave at runtime? It would certainly throw exception. This is what compiler prevents, by showing a compiler error.
We can add more information to the type parameter T
by specifying a bound - T extends Number
. But that will only allow us to access methods of type parameter. Constructor is still not accessible.