Невозможно создать типичный тип данных в классе
У меня есть неизменяемый класс со следующим расположением,
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
. Теперь, я думаю, это связано с возможно type erasure
в Java.
Как я могу это преодолеть? Я хочу добавить новую копию аргумента, который передается addData в мой список.
Ответы
Ответ 1
В java-языке генерические средства реализуются путем стирания, поэтому невозможно создать экземпляр типового типа. Также невозможно вызвать массив общего типа и т.д.
Как я могу это преодолеть? Я хочу добавить новую копию аргумента который передается в addData в мой список.
Вы можете попробовать использовать интерфейс Cloneable
как привязку типа или добавить свой собственный аналогичный интерфейс.
Ответ 2
T newT = (T) t.getClass().newInstance() // assuming zero args constructor and you'll
// have to catch some reflection exceptions
Ответ 3
В Java 8 вы можете передать lambda factory, которая создаст новый экземпляр требуемого типа:
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) );
В качестве оболочки для обратного вызова может использоваться встроенный аргумент no-argument Supplier.
Ответ 4
Вы можете использовать метод 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;
}
.........
}
Ответ 5
Я искал решение подобной проблемы. Вот решение, которое я сделал:
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());
}
}
Надеюсь, это поможет кому-то.
Ответ 6
вы можете получить тип работы T
Type type = new TypeToken<T>(){}.getType();
тогда получите экземпляр T do
type.getClass().newInstance();
Полный пример
public T foo() {
try {
return (T) type.getClass().newInstance();
} catch (Exception e) {
return null;
}
}