【问题标题】:How to initialize generic array?如何初始化泛型数组?
【发布时间】:2018-05-10 05:42:03
【问题描述】:

此方法用于将数组拆分为块reference。我想让这个方法通用。

问题是,我不能这样初始化数组。

T[][] arrays = new T[chunks][];

完整的方法

 public <T> T[][] splitArray(T[] arrayToSplit, int chunkSize) {
        if (chunkSize <= 0) {
            return null;
        }
        int rest = arrayToSplit.length % chunkSize;
        int chunks = arrayToSplit.length / chunkSize + (rest > 0 ? 1 : 0);
        T[][] arrays = new T[chunks][];
        for (int i = 0; i < (rest > 0 ? chunks - 1 : chunks); i++) {
            arrays[i] = Arrays.copyOfRange(arrayToSplit, i * chunkSize, i * chunkSize + chunkSize);
        }
        if (rest > 0) {
            arrays[chunks - 1] = Arrays.copyOfRange(arrayToSplit, (chunks - 1) * chunkSize, (chunks - 1) * chunkSize + rest);
        }
        return arrays;
    }

什么是初始化泛型数组的正确方法?

【问题讨论】:

    标签: java arrays


    【解决方案1】:

    您不能使用泛型参数初始化数组。 That is a restriction on generics.

    一种解决方法是创建一个Object[][] 并将其转换为T[][]

    T[][] arrays = (T[][])new Object[chunks][];
    

    【讨论】:

    • 第一个参数类型错误。找到:'byte[]',必需:'T[]'
    • 为什么调用这个方法会报错。
    • 你能告诉语法也调用这个方法吗?
    • @Khemraj 因为你的方法是通用的,你不能用原始类型调用它:docs.oracle.com/javase/tutorial/java/generics/… 使用Byte[](注意大写字母)。
    • 感谢您对有用链接的帮助,我一定会研究通用文档以提高我的理解。
    【解决方案2】:

    你不能创建一个泛型数组,但你可以声明一个泛型数组。

    T[] test = null; // works
    T[] test2 = new T[10]; // fails
    T[] test3 = (T[]) new Object[10]; // works
    

    同时,你should be careful with this

    【讨论】:

    • 有什么方法可以声明一个泛型数组而不需要 java 编译器记录“使用未经检查或不安全的操作”。在编译执行此操作的文件时? test3 导致该警告
    • @notacorn 不,因为你不能声明一个泛型数组,你将总是有转换为T[],总是。
    【解决方案3】:

    你不能直接创建一个泛型数组,因为类型变量信息在运行时会因为擦除而丢失。

    但是,在您的情况下,有一种解决方法,因为该方法的输出类型只是 arrayToSplit 类型的数组,而 Java 中的数组 do 在运行时提供其类型信息。

    所以而不是:

    T[][] arrays = new T[chunks][];

    你可以这样做:

    T[][] arrays = (T[][])Array.newInstance(arrayToSplit.getClass(), chunks);

    不过,混合使用数组和泛型可能会令人困惑且容易出错。如果可能,我会尽可能使用集合 API,并使用 List&lt;T&gt; 而不是数组。

    Guava 甚至有一个我认为完全符合您要求的方法:

    Lists.partition(List, int)

    返回列表的连续子列表,每个子列表大小相同(最终列表可能更小)。例如,将包含 [a, b, c, d, e] 的列表分区大小为 3 会产生 [[a, b, c], [d, e]] - 一个包含两个内部列表的外部列表三和二元素,都按照原来的顺序。

    【讨论】:

      猜你喜欢
      • 2014-04-05
      • 1970-01-01
      • 2013-10-21
      • 2010-10-02
      • 1970-01-01
      • 2019-03-16
      • 2015-03-22
      • 1970-01-01
      • 2020-03-15
      相关资源
      最近更新 更多