Troubleshooting
以下示例显示了对阵列进行操作时可能发生的典型错误。
IllegalArgumentException 由于类型不可转换
ArrayTroubleAgain示例将生成IllegalArgumentException。调用Array.setInt()来设置参考类型为Integer
的组件,其值的原始类型为int
。在非反射等效项ary[0] = 1
中,编译器会将值1
转换(或* box *)为参考类型new Integer(1)
,以便其类型检查将接受该语句。使用反射时,类型检查仅在运行时发生,因此没有机会将值装箱。
import java.lang.reflect.Array;
import static java.lang.System.err;
public class ArrayTroubleAgain {
public static void main(String... args) {
Integer[] ary = new Integer[2];
try {
Array.setInt(ary, 0, 1); // IllegalArgumentException
// production code should handle these exceptions more gracefully
} catch (IllegalArgumentException x) {
err.format("Unable to box%n");
} catch (ArrayIndexOutOfBoundsException x) {
x.printStackTrace();
}
}
}
$ java ArrayTroubleAgain
Unable to box
为了消除此异常,应将以下行Array.set(对象数组,整数索引,对象值)替换为有问题的行:
Array.set(ary, 0, new Integer(1));
Tip:
使用反射设置或获取数组组件时,编译器没有机会执行装箱。它只能转换与Class.isAssignableFrom()规范中所述相关的类型。该示例预计会失败,因为isAssignableFrom()
在此测试中将返回false
,可以通过编程将其用于验证特定转换是否可行:
Integer.class.isAssignableFrom(int.class) == false
同样,从原始类型到引用类型的自动转换也无法反映出来。
int.class.isAssignableFrom(Integer.class) == false
空数组的 ArrayIndexOutOfBoundsException
ArrayTrouble示例说明了如果try访问零 Long 度数组的元素将发生的错误:
import java.lang.reflect.Array;
import static java.lang.System.out;
public class ArrayTrouble {
public static void main(String... args) {
Object o = Array.newInstance(int.class, 0);
int[] i = (int[])o;
int[] j = new int[0];
out.format("i.length = %d, j.length = %d, args.length = %d%n",
i.length, j.length, args.length);
Array.getInt(o, 0); // ArrayIndexOutOfBoundsException
}
}
$ java ArrayTrouble
i.length = 0, j.length = 0, args.length = 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
at java.lang.reflect.Array.getInt(Native Method)
at ArrayTrouble.main(ArrayTrouble.java:11)
Tip:
可能有没有元素的数组(空数组)。在普通代码中只有少数情况可以看到它们,但是它们可能会在无意中反射发生。当然,不可能设置/获取空数组的值,因为将抛出ArrayIndexOutOfBoundsException。
IllegalArgumentException 如果try缩小
ArrayTroubleToo示例包含失败的代码,因为它try执行可能会丢失数据的操作:
import java.lang.reflect.Array;
import static java.lang.System.out;
public class ArrayTroubleToo {
public static void main(String... args) {
Object o = new int[2];
Array.setShort(o, 0, (short)2); // widening, succeeds
Array.setLong(o, 1, 2L); // narrowing, fails
}
}
$ java ArrayTroubleToo
Exception in thread "main" java.lang.IllegalArgumentException: argument type
mismatch
at java.lang.reflect.Array.setLong(Native Method)
at ArrayTroubleToo.main(ArrayTroubleToo.java:9)
Tip:
Array.set*()
和Array.get*()
方法将执行自动加宽转换,但是如果try进行缩小转换将抛出IllegalArgumentException。有关扩大和缩小转换的完整讨论,请分别参见Java 语言规范,Java SE 7 版,扩大原始转换和缩小原始转换部分。