如何根据Java中输入变量的未知列表类型声明变量?
如何根据Java中输入变量的未知列表类型声明变量 例如: 如果给定了arr1,则需要(浅层)从arr1复制到arr2。但您不知道arr1是什么类型的列表 这是我使用的代码,如果我想声明arr2,我必须检查列表类型的所有可能情况如何根据Java中输入变量的未知列表类型声明变量?,java,declare,variable-types,Java,Declare,Variable Types,如何根据Java中输入变量的未知列表类型声明变量 例如: 如果给定了arr1,则需要(浅层)从arr1复制到arr2。但您不知道arr1是什么类型的列表 这是我使用的代码,如果我想声明arr2,我必须检查列表类型的所有可能情况 静态列表函数(列表arr1、列表arr2){ if(ArrayList的arr1实例){ arr2=新的ArrayList(arr1); }else if(链接列表的arr1实例){ arr2=新链接列表(arr1); }否则如果(…){ ; } 返回arr2; } 有
静态列表函数(列表arr1、列表arr2){
if(ArrayList的arr1实例){
arr2=新的ArrayList(arr1);
}else if(链接列表的arr1实例){
arr2=新链接列表(arr1);
}否则如果(…){
;
}
返回arr2;
}
有没有更简单的方法根据arr1的类型声明arr2
也许只是看起来像::
需要静态列表(列表arr1、列表arr2){
arr2=新的XXXList(arr1);//其中XXXList基于arr1所在的列表类型
返回arr2;
}
除非我完全误解了您的问题,否则这就是您需要的(Java 8)
公共类ListCopyDemo{
公共静态void main(字符串[]args){
List original=新的ArrayList();
原创。添加(“你好,世界!”);
添加(“欢迎使用Java”);
List copy=ListCopyDemo.funcOri(原件);//应返回原件的副本
}
公共静态列表funcOri(列表arr1){
返回arr1.stream().collect(Collectors.toList());
}
}
如果要将
original
List类型更改为List
或LinkedList
,则functori
将起到相同的作用。您始终可以尝试使用反射创建arr1类的新实例
public class ListClone {
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
List<String> al = new ArrayList<>();
al.add("abc");
List<String> ll = new LinkedList<>();
ll.add("123");
List<String> alc = funcOri(al);
List<String> llc = funcOri(ll);
System.out.println(alc.getClass().getSimpleName());
System.out.println(llc.getClass().getSimpleName());
alc.add("def");
llc.add("456");
System.out.println(al);
System.out.println(alc);
System.out.println(ll);
System.out.println(llc);
}
static <T> List<T> funcOri(List<T> arr1) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Constructor<? extends List> constructor = arr1.getClass().getConstructor(Collection.class);
constructor.setAccessible(true);
return constructor.newInstance(arr1);
}
}
编辑
这假设arr1的列表类型有一个构造函数来获取集合。当然,完全有可能有列表实现没有。一个稍微安全一点的解决方案可能是使用默认构造函数并使用List.addAll()复制内容,但我们仍然不能确定所有列表实现是否都有默认构造函数。然后它将抛出NoSuchMethodException。您不需要重新创建
arr2=new ArrayList(arr1)
,因为它已经是ArrayList了。通常,arr1的确切列表类型是不相关的。如果您需要arr1的副本,关于arr2的实际列表类型的决定应基于您将如何使用arr2,即如果您将在任意位置插入项目,则LinkedLisr可能更好。但在大多数情况下,ArrayList已经足够好了。如果确实需要提供复制对象的同一类,可以使用clone()
方法或反射来创建原始列表的实例:public static list functori(list original)抛出reflectionOperationException{Objects.requirennull(original);List copy=original.getClass().getDeclaredConstructor().newInstance();copy.addAll(original);return copy;}
此实现不保证funcOri
返回与输入arr1
中完全相同的列表实现:这不是我想要的。返回值是一个数组列表。我尝试了以下操作:``公共静态void main(String[]args){List al=new ArrayList();al.add(“abc”);List ll=new LinkedList();ll.add(“123”);List alc=funcOri(al);List llc=funcOri(ll);System.out.println(al.getClass());System.out.println(ll.getClass();System.out.println(alc.getClass());System.out.println(llc.getClass());}```
public class ListClone {
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
List<String> al = new ArrayList<>();
al.add("abc");
List<String> ll = new LinkedList<>();
ll.add("123");
List<String> alc = funcOri(al);
List<String> llc = funcOri(ll);
System.out.println(alc.getClass().getSimpleName());
System.out.println(llc.getClass().getSimpleName());
alc.add("def");
llc.add("456");
System.out.println(al);
System.out.println(alc);
System.out.println(ll);
System.out.println(llc);
}
static <T> List<T> funcOri(List<T> arr1) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Constructor<? extends List> constructor = arr1.getClass().getConstructor(Collection.class);
constructor.setAccessible(true);
return constructor.newInstance(arr1);
}
}
ArrayList
LinkedList
[abc]
[abc, def]
[123]
[123, 456]