簡體   English   中英

無法在類中實例化通用數據類型

[英]Cannot instantiate generic data type in class

我有一個不可變的類,具有以下布局,

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;
    }
    .........
}

我在這里得到的錯誤是cannot instantiate type T 現在,我認為這與Java中的type erasure有關。

我怎么能克服這個? 我想添加一個新的參數副本,該副本將傳遞給我的列表中的addData。

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

在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;
    }
    .........
}

像這樣使用它,例如:

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

內置的無參數Supplier接口可以用作回調的包裝器。

我尋找類似問題的解決方案。 這是我做的解決方案:

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());
}

}

希望這會對某人有所幫助。

在java語言中,泛型是通過擦除實現的,因此不可能實例化泛型類型。 此外,也無法通過一般類型的數組來等等。

我怎么能克服這個? 我想添加一個新的參數副本,該副本將傳遞給我的列表中的addData。

您可以嘗試將Cloneable接口用作類型綁定或添加您自己的類似接口。

您可以像這樣使用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;
    }
    .........
}

你可以得到T的類型

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

然后得到一個T做的實例

type.getClass().newInstance();

完整的例子

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM