【问题标题】:How to declare a variable according to an unknown List type of the input variable in Java?如何根据Java中输入变量的未知List类型声明变量?
【发布时间】:2020-12-27 07:40:04
【问题描述】:

Java中如何根据输入变量的未知List类型声明变量?

例如::

给定 arr1,你需要从 arr1 (浅)复制到 arr2。但是你不知道 arr1 是什么类型的列表。

这是我使用的代码,如果我要声明arr2,我必须遍历所有可能的List类型的情况。

  static List<Object> funcOri(List<Object> arr1, List<Object> arr2) {
    if (arr1 instanceof ArrayList<?>) {
      arr2 = new ArrayList<Object>(arr1);
    } else if (arr1 instanceof LinkedList<?>) {
      arr2 = new LinkedList<Object>(arr1);
    } else if (...) {
      ;
    }
    return arr2;
  }

根据 arr1 的类型声明 arr2 有没有更简单的方法?

也许只是看起来像::

  static List<Object> funcWanted(List<Object> arr1, List<Object> arr2) {
    arr2 = new XXXList<Object>(arr1); // where XXXList is base on the type of list the arr1 is
    return arr2;
  }

【问题讨论】:

  • 你不需要重新创建arr2 = new ArrayList&lt;Object&gt;(arr1),因为它已经是ArrayList了。
  • 通常与 arr1 的确切列表类型无关。如果您需要 arr1 的副本,则对 arr2 的实际列表类型的决定应基于您要对 arr2 执行的操作,即如果您要在任意位置插入项目,LinkedLisr 可能会更好。但在大多数情况下,ArrayList 就足够了。
  • 如果你真的需要提供同一个类的拷贝对象,可以使用clone()方法或者反射来创建原始列表的实例:@ 987654325@

标签: java declare variable-types


【解决方案1】:

您始终可以尝试使用反射创建 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);
    }
}

输出:

ArrayList
LinkedList
[abc]
[abc, def]
[123]
[123, 456]

编辑

这假定 arr1 的列表类型有一个构造函数来获取一个 Collection。当然,完全有可能存在没有的 List 实现。一个更安全的解决方案可能是使用默认构造函数并使用 List.addAll() 复制内容,但我们仍然不能确定所有 List 实现都有默认构造函数。然后它会抛出 NoSuchMethodException。

【讨论】:

    【解决方案2】:

    除非我完全误解了你的问题,否则这就是你需要的(Java 8)

    public class ListCopyDemo {
        
        public static void main (String[] args) {
            List<String> original = new ArrayList<>();
            original.add("Hello World!");
            original.add("Welcome to Java");
            
            List<?> copy = ListCopyDemo.funcOri(original); // should return a copy of the original
        }
        
        public static List<Object> funcOri(List<?> arr1) {
            return arr1.stream().collect(Collectors.toList());
        }
    }
    

    如果您要将original 列表类型更改为List&lt;Integer&gt;LinkedList&lt;String&gt;funcOri 的工作方式相同。

    【讨论】:

    • 此实现不保证funcOri返回的列表实现与输入arr1中完全相同:What kind of list does collectors.toList() return
    • 这不是我想要的。返回值是某种方式的 ArrayList。我尝试了以下方法:``` public static void main(String[] args) { List al = new ArrayList(); al.add("abc");列表 ll = new LinkedList(); ll.add("123");列表 alc = funcOri(al);列表 llc = funcOri(ll); System.out.println(al.getClass()); System.out.println(ll.getClass()); System.out.println(alc.getClass()); System.out.println(llc.getClass()); } ```
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    • 2016-05-10
    相关资源
    最近更新 更多