创建类型为T的N维数组并填充它

时间:2014-09-12 23:08:10

标签: java arrays generics casting

我目前正在开发一个小型系统,我将从byte数组中读取某些值。其中一种类型必须是数组。其他类型是基元和字符串。

我遇到的问题是尝试创建并填充数组。从一个方法填充数组,我们称之为next()next()将返回非null Object - 此对象不是数组。长度也是动态的,并且从另一个源加载,但是对于以下代码,它将仅被提供。

final Integer[][] array = readArray(Integer[][].class, 10);
//... 

// T = Integer[][]
// S = Integer[]
public static <T, S> S[] readArray(final Class<T> cls, final int length) {
    if (cls.isArray()) {
        final Class<S> subCls = (Class<S>) cls.getComponentType();
        final S[] array = (S[]) Array.newInstance(subCls, length);
        for (int i = 0; i < length; i++) {
            if (subCls.isArray()) {
                array[i] = readArray(subCls, length);
            } else {
                array[i] = (S) next();
            }
        }
        return array;
    }
    throw new IllegalArgumentException("Type of cls must be an array.");
}

到目前为止,我有这个。目前的问题在于:

array[i] = readArray(subCls, length);

错误是:

Error:(28, 41) java: incompatible types: no instance(s) of type variable(s) T,S exist so that S[] conforms to S

我已经尝试了很多方法。包括使用HelperArray<T, S>类,但即使这样也行不通。

我还想指出数组的类型可能无法保证。唯一真正的保证是数组的顶级组件类型将是字符串或基元。例如,以下情况很可能发生:

Object[][]{String[]{}, Integer[]{}, byte[]{}}

非常感谢任何有关此问题的帮助,谢谢。

2 个答案:

答案 0 :(得分:2)

我把它拼凑在一起,这对你有帮助吗?

对我来说,输出是10x10二维数组,包含全部。

public class Test {

    public static void main(String[] args) {
        Integer[][] array = readArray(Integer[][].class, 10);

        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++)
                System.out.print(array[i][j] + ",");
            System.out.println();
        }
    }

    // T = Integer[][]
    // S = Integer[]
    public static <T, S> S[] readArray(final Class<T> cls, final int length) {
        if (cls.isArray()) {
            final Class<S> subCls = (Class<S>) cls.getComponentType();
            final S[] array = (S[]) Array.newInstance(subCls, length);
            for (int i = 0; i < length; i++) {
                if (subCls.isArray()) {
                    array[i] = (S) readArray((Class<?>) subCls, length);
                } else {
                    array[i] = (S) next();
                }
            }
            return array;
        }
        throw new IllegalArgumentException("Type of cls must be an array.");
    }

    private static Object next() {
        // TODO Auto-generated method stub
        return 1;
    }
}

答案 1 :(得分:0)

所以,让它发挥作用。当遗留代码中断并且我必须重写它时,3年内会自杀,但我将来会处理这个问题。从技术上讲,@ Libece在他的回答中是正确的 - 我只是忘记了导致这个问题的原语 - 实际上 - 指数级更难。

警告:未来的代码Gore [NSFW]

public synchronized <T, S> T readArray(final Class<T> cls) {
    if (next() != IDENTIFIER_ARRAY) {
        throw new InvalidProtocolException(lastReadIndex);
    }
    final int nextID = next();
    final int length = readRawInt();
    final Class<S> component = (Class<S>) cls.getComponentType();
    if (component.isPrimitive()) {
        switch (component.getCanonicalName()) {
            case "boolean":
                return (T) readRawBooleanArray(length);
            case "byte":
                return (T) readRawByteArray(length);
            case "short":
                return (T) readRawShortArray(length);
            case "char":
                return (T) readRawCharArray(length);
            case "int":
                return (T) readRawIntArray(length);
            case "float":
                return (T) readRawFloatArray(length);
            case "long":
                return (T) readRawLongArray(length);
            case "double":
                return (T) readRawDoubleArray(length);
        }
    }
    final S[] array = (S[]) Array.newInstance(component, length);
    for (int i = 0; i < length; i++) {
        if (component.isArray()) {
            array[i] = (S) readArray((Class<?>) component); // Thanks Icewind!
        } else {
            array[i] = (S) readMethodFor(nextID);
        }
    }
    return (T) array;
}