此Java教程是针对JDK 8编写的。本页面中描述的示例和实践不利用后续版本中引入的改进,并且可能使用不再可用的技术。
有关Java SE 9及后续版本中更新的语言特性的摘要,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能和已删除或弃用选项的信息,请参阅JDK发布说明。
以下示例显示了在操作数组时可能发生的典型错误。
示例将生成一个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("无法装箱%n"); } catch (ArrayIndexOutOfBoundsException x) { x.printStackTrace(); } } }
$ java ArrayTroubleAgain 无法装箱
要消除此异常,应将问题行替换为以下调用: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); // 扩大转换,成功 Array.setLong(o, 1, 2L); // 缩小转换,失败 } }
$ 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的扩大的基本类型转换和缩小的基本类型转换章节。