Search code examples
javagenericsinstancetype-parameter

Generic class and non static method


We have following code:

class MyClass<T>{
    public void method(){
        List<T>= new ArrayList<T>();
    }
}

Does the following reason is correct? We are trying to instanciate ArrayList<T>, where T is type parameter, from a non static method. method needs in a specific instance of MyClass<T>. For instanciate MyClass<T> compiler must know type T explicitly. As i understood, compiler mark type parametr T in a non static context as known and hence we can instanciate ArrayList<T>.

But if we write the following code:

class MyClass<T>{
    public void method(){
        List<T>= new ArrayList<T>();
        new T();// Compile Error
    }
}

We have a compile error. I know that we can apply abstract factory pattern or use reflection for that needs. But new operator requires a specific type. Type parametr T is specific i non static context. Where i've wrong reasoning?


Solution

  • 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.