假设我有一个对象类和一个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
?
答案 0 :(得分: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
编辑:添加了一个稍微难看的修复来处理单维数组
答案 1 :(得分:0)
查看java.lang.reflect.Array
课程,还有其他有用的方法,例如get(Object array, int index)
和setFloat(Object array, int index, float f)
。使用这些的组合,应该能够填充整个多维数组。
粗伪代码:
Object level0 = createArray(...)
For i1 = 0 to (length of dimension 1) {
Object level1 = get(level0, i1)
For i2 = 0 to (length of dimension 2) {
Object level2 = get(level1, i2)
...etc...
For iM = 0 to (length of dimension M) {
Object levelM = get(levelL, iM)
For iN = 0 to (length of dimension N) {
setFloat(levelM, iN, 5.6f)
}
}
...
}
}
如果我正确地阅读API,那么这样的事情应该有效。
答案 2 :(得分: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;
}