有可能在Java中创建泛型类型的实例吗?我在想,根据我所看到的,答案是否定的(由于类型擦除),但如果有人能看到我遗漏的东西,我会很感兴趣:

class SomeContainer<E>
{
    E createContents()
    {
        return what???
    }
}

编辑:事实证明,超级类型令牌可以用来解决我的问题,但它需要大量基于反射的代码,如下面的一些答案所示。

我将把这个问题放一段时间,看看是否有人提出了与Ian Robertson的Artima文章截然不同的东西。


当前回答

考虑一种更函数化的方法:与其凭空创建一些E(这显然是一种代码味道),不如传递一个知道如何创建E的函数。

E createContents(Callable<E> makeone) {
     return makeone.call(); // most simple case clearly not that useful
}

其他回答

考虑一种更函数化的方法:与其凭空创建一些E(这显然是一种代码味道),不如传递一个知道如何创建E的函数。

E createContents(Callable<E> makeone) {
     return makeone.call(); // most simple case clearly not that useful
}

这是我想到的一个选择,可能会有帮助:

public static class Container<E> {
    private Class<E> clazz;

    public Container(Class<E> clazz) {
        this.clazz = clazz;
    }

    public E createContents() throws Exception {
        return clazz.newInstance();
    }
}

EDIT:你也可以使用这个构造函数(但它需要一个E的实例):

@SuppressWarnings("unchecked")
public Container(E instance) {
    this.clazz = (Class<E>) instance.getClass();
}

在Java 8中,你可以使用Supplier函数接口很容易地实现这一点:

class SomeContainer<E> {
  private Supplier<E> supplier;

  SomeContainer(Supplier<E> supplier) {
    this.supplier = supplier;
  }

  E createContents() {
    return supplier.get();
  }
}

你可以这样构造这个类:

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

这一行上的String::new语法是一个构造函数引用。

如果你的构造函数接受参数,你可以使用lambda表达式:

SomeContainer<BigInteger> bigIntegerContainer
    = new SomeContainer<>(() -> new BigInteger(1));

当您在编译时使用E时,您并不真正关心实际的泛型类型“E”(无论是使用反射还是使用泛型类型的基类),因此让子类提供E的实例。

abstract class SomeContainer<E>
{
    abstract protected E createContents();
    public void doWork(){
        E obj = createContents();
        // Do the work with E 
     }
}

class BlackContainer extends SomeContainer<Black>{
    protected Black createContents() {
        return new Black();
    }
}

你可以通过下面的代码片段来实现这一点:

import java.lang.reflect.ParameterizedType;

public class SomeContainer<E> {
   E createContents() throws InstantiationException, IllegalAccessException {
      ParameterizedType genericSuperclass = (ParameterizedType)
         getClass().getGenericSuperclass();
      @SuppressWarnings("unchecked")
      Class<E> clazz = (Class<E>)
         genericSuperclass.getActualTypeArguments()[0];
      return clazz.newInstance();
   }
   public static void main( String[] args ) throws Throwable {
      SomeContainer< Long > scl = new SomeContainer<>();
      Long l = scl.createContents();
      System.out.println( l );
   }
}