Java:可以将通配符数组类型用作参数和返回类型吗?

时间:2015-10-10 14:44:58

标签: java generics polymorphism

例如,考虑一个函数,该函数接受String的ArrayList并将其拆分为String数组,并返回这些新数组的ArrayList:

public static ArrayList<String[]> splitListIntoArrays(ArrayList<String> list, int divisor) {
    ArrayList<String> listSplit = new ArrayList<>();
    ArrayList<String[]> listOfArrays = new ArrayList<>();
    for (int i = 0; i < list.size(); i++) {
        listSplit.add(list.get(i));
        if ((listSplit.size() + divisor) % divisor == 0 || i == (list.size() - 1)) {
        listOfArrays.add(listSplit.toArray(new String[listSplit.size()]));
        listSplit = new ArrayList<>();
        }
    }
    return listOfArrays;
    }

现在,假设我想做同样的事情,但是对于Long的ArrayList:

public static ArrayList<Long[]> splitListIntoArrays(ArrayList<Long> list, int divisor) {
    ArrayList<Long> listSplit = new ArrayList<>();
    ArrayList<Long[]> listOfArrays = new ArrayList<>();
    for (int i = 0; i < list.size(); i++) {
        listSplit.add(list.get(i));
        if ((listSplit.size() + divisor) % divisor == 0 || i == (list.size() - 1)) {
        listOfArrays.add(listSplit.toArray(new Long[listSplit.size()]));
        listSplit = new ArrayList<>();
        }
    }
    return listOfArrays;
    }

是否有最好的方法可以避免代码重复?

1 个答案:

答案 0 :(得分:7)

定义通用方法似乎是最自然的方法:

  public static <T> List<T[]> splitListIntoArrays(List<T> list, int divisor)
  {
    ArrayList<T> listSplit = new ArrayList<>();
    ArrayList<T[]> listOfArrays = new ArrayList<>();
    for (int i = 0; i < list.size(); i++)
    {
        listSplit.add(list.get(i));
        if ((listSplit.size() + divisor) % divisor == 0 || i == (list.size() - 1))
        {
          listOfArrays.add(listSplit.toArray(new T[listSplit.size()]));
          listSplit = new ArrayList<>();
        }
    }
    return listOfArrays;
  }

我将ArrayList<T>替换为List<T>界面,因为它更通用。

代码很好但是有一个问题:你不能创建一个通用数组,所以这个

new T[listSplit.size()]

不是有效的Java代码。

这些问题有多种解决方案,其中很多都依赖于反思。更好,最快的解决方案是将类直接传递给方法,以便您可以使用反射来实例化数组:

  public static <T> List<T[]> splitListIntoArrays(List<T> list, int divisor, Class<T> clazz)
  {
    ArrayList<T> listSplit = new ArrayList<>();
    ArrayList<T[]> listOfArrays = new ArrayList<>();
    for (int i = 0; i < list.size(); i++)
    {
        listSplit.add(list.get(i));
        if ((listSplit.size() + divisor) % divisor == 0 || i == (list.size() - 1))
        {
          @SuppressWarnings("unchecked")
          T[] array = (T[]) java.lang.reflect.Array.newInstance(clazz, listSplit.size());

          listOfArrays.add(listSplit.toArray(array));
          listSplit = new ArrayList<>();
        }
    }
    return listOfArrays;
  }

以便现在可以使用:

  static void test()
    {
      List<String> test = Arrays.asList("foo", "bar", "baz", "foobar", "barbaz");
      List<String[]> split = splitListIntoArrays(test, 2, String.class);
      split.forEach(s -> java.lang.System.out.println(Arrays.toString(s)));


      List<Long> test2 = Arrays.asList(1L,2L,3L,4L,5L);
      List<Long[]> split2 = splitListIntoArrays(test2, 2, Long.class);
      split2.forEach(s -> java.lang.System.out.println(Arrays.toString(s)));
    }

输出:

[foo, bar]
[baz, foobar]
[barbaz]
[1, 2]
[3, 4]
[5]