3

オブジェクト クラスと、int[]インスタンス化 (および操作) したい多次元配列の任意の長さを記述する が与えられたとします。これまでのところ、 を使用できることがわかりましたjava.lang.reflect.Array.newInstance(Class<?> type, int... sizes)が、その時点で立ち往生しています。言い換えると、

Class<?> type = float.class;  // this varies (I receive this)
int[] sizes = new int[]{ 10, 400, 300 }; // this varies too, it could be e.g. int[]{0} for a scalar
Object o = (Object) java.lang.reflect.Array.newInstance(type, sizes);

定義した後Object o、続行する方法がわかりません。typeアプリオリに、 がなるか、他の型になるかはわかりませんfloat.class(今のところ、基本型であると想定しています)。それより悪い、int[] sizes何でもありえます。

より具体的な問題にするために、たとえば、多次元配列の各要素にo特定の値を設定するにはどうすれ5.6ばよいArray.newInstanceでしょうか?

4

3 に答える 3

1

良い質問。オブジェクトを特定の次元の配列にキャストする方法がないように見えるため、これは非常に注意が必要です。作成されたインスタンスから適切な多次元配列オブジェクトを取得する方法が見つかりませんでした。ただし、作成した配列の要素を取得および設定するだけの場合は、次のメソッドを使用できます。

public static void main(String[] args) {
    Class<?> type = float.class; // this varies (I receive this)
    int[] sizes = new int[] { 1, 3 }; // this varies too, it could be e.g.
                                    // int[]{0} for a scalar
    Object f = Array.newInstance(type, sizes);
    set(f, new int[] { 0, 2 }, 3.0f);
    if (f instanceof Object[])
        System.out.println(Arrays.deepToString((Object[]) f));
    else {
        int l = Array.getLength(f);
        for (int i = 0; i < l; ++i) {
            System.out.print(Array.get(f, i) + ", ");
        }
        System.out.println();
    }
}

public static void set(Object arr, int[] indexPath, Object value) {
    if (arr instanceof Object[]) {
        Object[] temp= (Object[]) arr;
        for (int i = 0; i < indexPath.length - 2; ++i) {
            temp = (Object[]) temp[indexPath[i]];
        }
        Array.set(temp[indexPath[indexPath.length - 2]],
            indexPath[indexPath.length - 1], value);
    } else {
        Array.set(arr,
                indexPath[0], value);
    }
}

このsetメソッドは、配列として設定するインデックスを受け取ります。set(f, new int[] {0,0,1}, 3.0f);基本的にそうすべきですf[0][0][1] = 3.0f

EDIT:一次元配列を処理するために少し醜い修正を追加しました

于 2013-10-14T11:22:35.390 に答える
0

Java APIから配列操作メソッドを見つけて使用しようとする代わりに、ソリューションをコーディングすることになりました(以下の唯一のものはjava.util.Arrays.copyOf(Object[], int).

というわけで、以下は私が書いた方法です。私はそれらを広範囲にテストしませんでした(非効率性があっても驚かないでしょう。最初にうまくいくように見えたものを試しただけです)。

/**
 * Creates an instance of Object multi-dimensional arrays, with dimensions specified by the argument.
 * 
 * @example Create an array Object[4][20][30]:  
 * <pre>
 * Object[] array = newArray(new int[]{4,20,30});
 * </pre>
 * 
 * @param sizes The list of dimension lengths.
 * @return 
 */
public static Object[] newArray(int[] sizes) {
    Object[] result = null;
    if (sizes != null) {
        for(int n = sizes.length - 1; n >= 0; n--) {
            if (result == null) {
                result = new Object[sizes[n]];
            } else {
                Object[] oa = new Object[sizes[n]];
                for (int i = 0; i < sizes[n]; i++) {
                    oa[i] = java.util.Arrays.copyOf(result, result.length);
                }
                result = oa;
            }
        }
        if (result == null) { result = new Object[1]; }
    }
    return result;
}

/**
 * Get the value of a multi-dimensional array element given by a coordinate list.
 * 
 * @example Read the value at [2][14][27]:
 * <pre>
 * Object[] array;  // e.g. a int[4][20][30] created with newArray(int[])
 * int[] coord = new int[]{2,14,27};
 * Object value = getValue(array, coord);
 * </pre>
 * 
 * @param array The coordinates of the array element.
 * @param coordinates
 * @return
 */
public static Object getValue(Object[] array, int[] coordinates) {
    Object result = null;
    if (array == null || coordinates == null || 0 > coordinates[0]||coordinates[0] > array.length) {
        result = null;
    } else {
        int x = coordinates[0];
        if (array[x] instanceof Object[]) {
            int[] c = new int[coordinates.length-1];
            for(int i = 0; i < c.length; i++) { c[i] = coordinates[i + 1]; }
            result = getValue((Object[]) array[x], c);
        } else {
            result = array[x];
        }
    }
    return result;
}

/**
 * Set the value of a multi-dimensional array element given a list designating the element's coordinates.
 * 
 * @example Write a value to [1][0][7]:
 * <pre>
 * Object value;    // e.g. a float
 * Object[] array;  // e.g. a int[4][20][30] created with newArray(int[])
 * int[] coord = new int[]{1,0,7,};
 * setValue(array, coord, value);
 * </pre>
 * 
 * @param array
 * @param coordinates
 * @param value
 * @return
 */
public static void setValue(Object[] array, int[] coordinates, Object value) {
    if (array == null || coordinates == null || array.length == 0 || coordinates.length == 0 || array.length < coordinates[0]||coordinates[0] < 0 ) {
        return;
    } else {
        int x = coordinates[0];
        if (array[x] != null && array[x].getClass().isArray()) {    // recurse
            int[] c = new int[coordinates.length - 1];
            for (int i = 0; i < c.length; i++) { c[i] = coordinates[i + 1]; }
            setValue((Object[]) array[x], c, value); 
        } else {
            array[x] = value;
        }
    }
    return;
}
于 2013-10-14T17:06:47.727 に答える