Create instance of generic type in Java?

后端 未结 27 3093
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-21 06:14

Is it possible to create an instance of a generic type in Java? I\'m thinking based on what I\'ve seen that the answer is no (due to type erasure), but

相关标签:
27条回答
  • 2020-11-21 06:56
    return   (E)((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
    
    0 讨论(0)
  • 2020-11-21 06:57

    If you want not to type class name twice during instantiation like in:

    new SomeContainer<SomeType>(SomeType.class);
    

    You can use factory method:

    <E> SomeContainer<E> createContainer(Class<E> class); 
    

    Like in:

    public class Container<E> {
    
        public static <E> Container<E> create(Class<E> c) {
            return new Container<E>(c);
        }
    
        Class<E> c;
    
        public Container(Class<E> c) {
            super();
            this.c = c;
        }
    
        public E createInstance()
                throws InstantiationException,
                IllegalAccessException {
            return c.newInstance();
        }
    
    }
    
    0 讨论(0)
  • 2020-11-21 06:57

    Here's an implementation of createContents that uses TypeTools to resolve the raw class represented by E:

    E createContents() throws Exception {
      return TypeTools.resolveRawArgument(SomeContainer.class, getClass()).newInstance();
    }
    

    This approach only works if SomeContainer is subclassed so the actual value of E is captured in a type definition:

    class SomeStringContainer extends SomeContainer<String>
    

    Otherwise the value of E is erased at runtime and is not recoverable.

    0 讨论(0)
  • 2020-11-21 06:59

    Dunno if this helps, but when you subclass (including anonymously) a generic type, the type information is available via reflection. e.g.,

    public abstract class Foo<E> {
    
      public E instance;  
    
      public Foo() throws Exception {
        instance = ((Class)((ParameterizedType)this.getClass().
           getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
        ...
      }
    
    }
    

    So, when you subclass Foo, you get an instance of Bar e.g.,

    // notice that this in anonymous subclass of Foo
    assert( new Foo<Bar>() {}.instance instanceof Bar );
    

    But it's a lot of work, and only works for subclasses. Can be handy though.

    0 讨论(0)
  • 2020-11-21 06:59

    In Java 8 you can use the Supplier functional interface to achieve this pretty easily:

    class SomeContainer<E> {
      private Supplier<E> supplier;
    
      SomeContainer(Supplier<E> supplier) {
        this.supplier = supplier;
      }
    
      E createContents() {
        return supplier.get();
      }
    }
    

    You would construct this class like this:

    SomeContainer<String> stringContainer = new SomeContainer<>(String::new);
    

    The syntax String::new on that line is a constructor reference.

    If your constructor takes arguments you can use a lambda expression instead:

    SomeContainer<BigInteger> bigIntegerContainer
        = new SomeContainer<>(() -> new BigInteger(1));
    
    0 讨论(0)
  • 2020-11-21 07:01

    You can use:

    Class.forName(String).getConstructor(arguments types).newInstance(arguments)
    

    But you need to supply the exact class name, including packages, eg. java.io.FileInputStream. I used this to create a math expressions parser.

    0 讨论(0)
提交回复
热议问题