Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
以下示例显示了在数组上操作时可能出现的典型错误。
示例将生成 ArrayTroubleAgainIllegalArgumentException。调用 Array.setInt() 以设置引用类型 Integer 的组件,其值为基本类型 int。在非反射等价物 ary[0] = 1 中,编译器会将值转换(装箱)为引用类型 1 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(Object array, int index, Object value):
Array.set(ary, 0, new Integer(1));
Class.isAssignableFrom() 规范所描述的相关类型。该示例预计会失败,因为 isAssignableFrom() 将在此测试中返回 false,可以通过编程方式验证是否可以进行特定转换:
Integer.class.isAssignableFrom(int.class) == false
类似地,在反射中也不可能从基本类型到引用类型的自动转换。
int.class.isAssignableFrom(Integer.class) == false
示例说明了在尝试访问零长度数组的元素时将发生的错误:ArrayTrouble
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)
ArrayIndexOutOfBoundsException。
示例包含失败的代码,因为它尝试执行可能会丢失数据的操作:ArrayTroubleToo
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)
Array.set*() 和 Array.get*() 方法将执行自动扩大转换,但如果尝试缩小转换会抛出 IllegalArgumentException。有关扩大和缩小转换的完整讨论,请分别参阅 The Java Language Specification, Java SE 7 Edition,Widening Primitive Conversion 和 Narrowing Primitive Conversion 部分。