Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无法在类中实例化泛型数据类型_Java_Generics - Fatal编程技术网

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

Java 无法在类中实例化泛型数据类型,java,generics,Java,Generics,我有一个不变的类,布局如下 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 ove

我有一个不变的类,布局如下

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;
    }
    .........
}
公开期末甲级{
私人ArrayList myList;
私人A(){
myList=新的ArrayList();
}
公共A添加数据(T){
A newOb=//创建一个新列表并使用重载构造函数实例化
T newT=new T();*********此处有错误*************
newOb.myList.add(newT);
返回newOb;
}
.........
}
我在这里得到的错误是
无法实例化类型T
。现在,我认为这可能与Java中的类型擦除有关


我怎样才能克服这个问题?我想添加一个新的参数副本,该参数用于将addData传递到我的列表中

在java语言中,泛型是通过擦除实现的,因此不可能实例化泛型类型。此外,不可能建立泛型类型的数组等等

我怎样才能克服这个问题?我想添加一个新的参数副本 正在传递以将数据添加到我的列表中

您可以尝试使用
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;
    }
    .........
}
公开期末甲级{
私人ArrayList myList;
私人A(){
myList=新的ArrayList();
}
公共A添加数据(T){
T newT=T.clone();
newOb.myList.add(newT);
返回newOb;
}
.........
}

您可以获得T do的类型

Type type = new TypeToken<T>(){}.getType();
type.getClass().newInstance();
完整示例

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

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

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());
}
公共最终类不可变a{
私人ArrayList myList;
私人课堂;
公共静态ImmutableA createEmpty(类clazz){
返回新的ImmutableA(clazz);
}
私有不可变表A(类clazz){
this.myList=new ArrayList();
this.clazz=clazz;
}
公共ImmutableA addData(T){
ImmutableA newOb=新的ImmutableA(clazz);
试一试{
构造函数=clazz.getDeclaredConstructor(clazz);
T newT=constructor.newInstance(T);
newOb.myList.add(newT);
返回newOb;
}catch(NoSuchMethodException | InvocationTargetException |实例化Exception | IllegaAccessException e){
e、 printStackTrace();
}
返回null;
}
公共阵列列表getMyList(){
返回myList;
}
publicstaticvoidmain(字符串[]args)抛出instanceionException、IllegalAccessException{
ImmutableA 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 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;
    }
    .........
}
公开期末甲级{
私人ArrayList myList;
私人A(){
myList=新的ArrayList();
}
公共A添加数据(供应商工厂){
A newOb=//创建一个新列表并使用重载构造函数实例化
T newT=factory.get();
newOb.myList.add(newT);
返回newOb;
}
.........
}
如下图所示:

A<Integer> a = new A<>();
a.addData( () -> new Integer(0) );
A A=新A();
a、 addData(()->新整数(0));

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

运行时可能会创建对象的副本。所以我们在运行时需要正确的字节码。在最大值时,Java擦除可以执行convert
T newT=new T()到运行时可用的对象newT=new Object()
。但这也是错误的,因为
T
可以是任何
扩展对象
而不仅仅是
对象
。因此编译器出现错误。假设我的T是Date,并且我确实
dated=new Date();A=新的A();a、 添加数据(d);d、 设定日期(10),那么列表中的值是否会更改?\n是的,您调用添加到列表中的可变对象的setter,以便也更改列表中的值。好的。这就是创建要插入的数据的新副本的主要目的。但结果证明它不起作用。如果您创建myList.add(d.clone())并调用d.setX(),则不会将该值更改为list@jolivier这个主意很好。但是我认为clone方法在泛型上不起作用。我使用了这个,t在我的类中是整数,它在运行时抛出异常。@sTEAK.:所以如果您可以执行
new t()
,当
T
Integer
时,它意味着什么?在complile时间,T被Object
Cloneable
替换,因为类型绑定是完全无用的,除非它使用正确并且实现了
clone()
,表达式的静态类型必须具有此方法,因此
T extends Object&Cloneable
更适用。很好的添加,我没有注意到。所有内容都自动扩展
对象
。那没关系
Object
clone
不是公共的,仅用于子类调用超级实现。Java中没有指定公共
clone
方法的抽象类型。这应该是一种方法,没有变通方法和/或假设……应该是公认的答案。我不擅长Java,但我想显式类型转换很少是一个好迹象。。。专业人士怎么说?
A<Integer> a = new A<>();
a.addData( () -> new Integer(0) );