Why can't you create an instance of a generic type using "new" operator?

traveh picture traveh · Jun 4, 2015 · Viewed 15.7k times · Source

I found a lot of posts about how to overcome this limitation, but none about why this limitation exists (except this one, which just mentions it has to do with type erasure).

So why can't you create an instance of a generic type?

To clarify, my question is not how it can be done. I know it's possible in C#, so why not in Java? I'm curious about why the Java folks did not implement a similar mechanism? Why force Java developers to use awkward workarounds that have the potential to result in a runtime error? Are there any potential hazards from such a mechanism?

Answer

AdamSkywalker picture AdamSkywalker · Jun 4, 2015

Short answer: Java is a compiled programming language, which means that your bytecode is constant at runtime. It is impossible to generate bytecode for new E() if E is unknown.

Explanation: Generic information is erased in runtime:

public class Container<E> {
     private E item;
     public E getItem() {return item;}
}
class BoxWithPresent extends Container<Present> {
}
class SimpleBox extends Container {
}

In bytecode class BoxWithPresent contains field item of type Present, but class SimpleBox contains field item of type Object (because type E was not specified).

Now you write abstract instantiation method:

public class Container<E> {
    public <E> E createE() {
        return new E(); // imagine if that was allowed
    }
}

What bytecode should be generated here? .class file is generated right now, at compilation time, but we have no idea what is E type.

So.. can new T() be replaced with new Object()? Bad idea, class BoxWithPresent won't like it, because it expects that E is Present.

Can it be replaced with class.newInstance()? Again no, there is no class variable in method scope.

That's why new E() is impossible.
But there are workarounds with passing class as parameter, or extracting generic information.