java 无法在类中实例化泛型数据类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12093541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 07:33:56  来源:igfitidea点击:

Cannot instantiate generic data type in class

javagenerics

提问by h4ck3d

I have an immutable class , with the following layout ,

我有一个不可变的类,具有以下布局,

public final class A <T> {
    private ArrayList<T> myList;
    private A(){
        myList = new ArrayList<T>();
    }
    public A<T> addData(T t){
        A newOb = // make a new list and instantiate using overloaded constructor
        T newT = new T(); ***********ERROR HERE*************
        newOb.myList.add(newT);
        return newOb;
    }
    .........
}

The error that I get here is cannot instantiate type T. Now , I think this is related to maybe type erasurein Java.

我在这里得到的错误是cannot instantiate type T. 现在,我认为这可能type erasure与 Java 相关。

How can I overcome this ? I want to add a new copy of the argument that is being passed to addData into my list.

我怎样才能克服这个?我想将传递给 addData 的参数的新副本添加到我的列表中。

采纳答案by gkuzmin

In java language generics are implemented by erasure, so it is impossible to instantiate a generic type. Also it is impossible to instiate an array of generic type and so on.

在java语言中泛型是通过擦除实现的,所以不可能实例化一个泛型类型。也不可能建立一个泛型类型的数组等等。

How can I overcome this ? I want to add a new copy of the argument that is being passed to addData into my list.

我怎样才能克服这个?我想将传递给 addData 的参数的新副本添加到我的列表中。

You can try to use Cloneableinterface as a type bound or add your own similar interface.

您可以尝试将Cloneable接口用作类型绑定或添加您自己的类似接口。

回答by Ransom Briggs

T newT = (T) t.getClass().newInstance() // assuming zero args constructor and you'll
                                        // have to catch some reflection exceptions

回答by rustyx

In Java 8 you can pass a factory lambdawhich would create a new instance of the desired type:

在 Java 8 中,您可以传递一个工厂 lambda,它将创建所需类型的新实例:

public final class A <T> {
    private ArrayList<T> myList;
    private A(){
        myList = new ArrayList<T>();
    }
    public A<T> addData(Supplier<T> factory){
        A newOb = // make a new list and instantiate using overloaded constructor
        T newT = factory.get();
        newOb.myList.add(newT);
        return newOb;
    }
    .........
}

Use it like this for example:

例如,像这样使用它:

A<Integer> a = new A<>();
a.addData( () -> new Integer(0) );

The built-in no-argument Supplierinterface can be used as the wrapper for the callback.

内置的无参数供应商接口可用作回调的包装器。

回答by Vitaly

I looked for solution of similar problem. Here is the solution I made:

我寻找类似问题的解决方案。这是我提出的解决方案:

public final class ImmutableA<T> {
private ArrayList<T> myList;
private Class<T> clazz;

public static <E> ImmutableA<E> createEmpty(Class<E> clazz) {
    return new ImmutableA<>(clazz);
}

private ImmutableA(Class<T> clazz) {
    this.myList = new ArrayList<T>();
    this.clazz = clazz;
}

public ImmutableA<T> addData(T t) {
    ImmutableA<T> newOb = new ImmutableA<>(clazz);
    try {
        Constructor<T> constructor = clazz.getDeclaredConstructor(clazz);
        T newT = constructor.newInstance(t);
        newOb.myList.add(newT);
        return newOb;
    } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

public ArrayList<T> getMyList() {
    return myList;
}

public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    ImmutableA<String> immutableA = createEmpty(String.class);
    System.out.print(immutableA.getMyList().toString());
    immutableA = immutableA.addData("a");
    System.out.print(immutableA.getMyList().toString());
    immutableA = immutableA.addData("b");
    System.out.print(immutableA.getMyList().toString());
    immutableA = immutableA.addData("c");
    System.out.print(immutableA.getMyList().toString());
}

}

}

Hope this will help to somebody.

希望这会对某人有所帮助。

回答by jolivier

You can use clone() method like this:

您可以像这样使用 clone() 方法:

public final class A <T extends Cloneable> {
    private ArrayList<T> myList;
    private A(){
        myList = new ArrayList<T>();
    }
    public A<T> addData(T t){
        T newT = t.clone();
        newOb.myList.add(newT);
        return newOb;
    }
    .........
}

回答by Luca Corradi

you can get the type of T doing

你可以得到 T 的类型

Type type = new TypeToken<T>(){}.getType();

then get an instance of T doing

然后得到一个 T 的实例做

type.getClass().newInstance();

Complete example

完整示例

public T foo() {
    try {
        return (T) type.getClass().newInstance();
    } catch (Exception e) {
        return null;
    }
}