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

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

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

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


当前回答

你能做的就是——

首先声明该泛型类的变量 2.然后创建它的构造函数并实例化该对象 那就在任何你想用的地方用吧

的例子,

1

私有类<E>实体;

2

public xyzservice(Class<E> entity) {
        this.entity = entity;
    }



public E getEntity(Class<E> entity) throws InstantiationException, IllegalAccessException {
        return entity.newInstance();
    }

3.

E E = getEntity(实体);

其他回答

注意,kotlin中的泛型类型可能没有默认构造函数。

 implementation("org.objenesis","objenesis", "3.2")

    val fooType = Foo::class.java
    var instance: T = try {
        fooType.newInstance()
    } catch (e: InstantiationException) {
//            Use Objenesis because the fooType class has not a default constructor
        val objenesis: Objenesis = ObjenesisStd()
        objenesis.newInstance(fooType)
    }

没有默认构造函数 Objenesis

你说得对。你不能用new E()。但是你可以把它改成

private static class SomeContainer<E> {
    E createContents(Class<E> clazz) {
        return clazz.newInstance();
    }
}

这是一种痛苦。但它确实有效。将其包装在工厂模式中使其更易于忍受。

当您在编译时使用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();
    }
}

我不知道这是否有帮助,但当您子类化(包括匿名)泛型类型时,类型信息可以通过反射获得。例如,

public abstract class Foo<E> {

  public E instance;  

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

}

所以,当你子类化Foo时,你得到Bar的一个实例,例如,

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

但是工作量很大,而且只适用于子类。不过也很方便。

对诺亚的回答进行了改进。

改变的原因

a]如果使用多于一个泛型类型,则更安全,以防您更改顺序。

b]类泛型类型签名会不时变化,这样你就不会对运行时中无法解释的异常感到惊讶。

健壮的代码

public abstract class Clazz<P extends Params, M extends Model> {

    protected M model;

    protected void createModel() {
    Type[] typeArguments = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
    for (Type type : typeArguments) {
        if ((type instanceof Class) && (Model.class.isAssignableFrom((Class) type))) {
            try {
                model = ((Class<M>) type).newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

或者使用一个眼线笔

一行代码

model = ((Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]).newInstance();