Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
以下示例显示了在数组上操作时可能出现的典型错误。
示例将生成 ArrayTroubleAgain
IllegalArgumentException
。调用 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 部分。