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被ObjectCloneable
替换,因为类型绑定是完全无用的,除非它使用正确并且实现了clone()
,表达式的静态类型必须具有此方法,因此T extends Object&Cloneable
更适用。很好的添加,我没有注意到。所有内容都自动扩展对象
。那没关系Object
的clone
不是公共的,仅用于子类调用超级实现。Java中没有指定公共clone
方法的抽象类型。这应该是一种方法,没有变通方法和/或假设……应该是公认的答案。我不擅长Java,但我想显式类型转换很少是一个好迹象。。。专业人士怎么说?
A<Integer> a = new A<>();
a.addData( () -> new Integer(0) );