The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
Just as in non-reflective code, an array field may be set or retrieved in its entirety or component by component. To set the entire array at once, use java.lang.reflect.Field.set(Object obj, Object value)
. To retrieve the entire array, use Field.get(Object)
. Individual components can be set or retrieved using methods in java.lang.reflect.Array
.
Array
provides methods of the form setFoo()
and getFoo()
for setting and getting components of any primitive type. For example, the component of an int
array may be set with Array.setInt(Object array, int index, int value)
and may be retrieved with Array.getInt(Object array, int index)
.
These methods support automatic widening of data types. Therefore, Array.getShort()
may be used to set the values of an int
array since a 16-bit short
may be widened to a 32-bit int
without loss of data; on the other hand, invoking Array.setLong()
on an array of int
will cause an IllegalArgumentException
to be thrown because a 64-bit long
can not be narrowed to for storage in a 32-bit int
with out loss of information. This is true regardless of whether the actual values being passed could be accurately represented in the target data type. The Java Language Specification, Java SE 7 Edition, sections Widening Primitive Conversion and Narrowing Primitive Conversion contains a complete discussion of widening and narrowing conversions.
The components of arrays of reference types (including arrays of arrays) are set and retrieved using Array.set(Object array, int index, int value)
and Array.get(Object array, int index)
.
The
example illustrates how to replace the value of a field of type array. In this case, the code replaces the backing array for a GrowBufferedReader
java.io.BufferedReader
with a larger one. (This assumes that the creation of the original BufferedReader
is in code that is not modifiable; otherwise, it would be trivial to simply use the alternate constructor BufferedReader(java.io.Reader in, int size)
which accepts an input buffer size.)
import java.io.BufferedReader; import java.io.CharArrayReader; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Field; import java.util.Arrays; import static java.lang.System.out; public class GrowBufferedReader { private static final int srcBufSize = 10 * 1024; private static char[] src = new char[srcBufSize]; static { src[srcBufSize - 1] = 'x'; } private static CharArrayReader car = new CharArrayReader(src); public static void main(String... args) { try { BufferedReader br = new BufferedReader(car); Class<?> c = br.getClass(); Field f = c.getDeclaredField("cb"); // cb is a private field f.setAccessible(true); char[] cbVal = char[].class.cast(f.get(br)); char[] newVal = Arrays.copyOf(cbVal, cbVal.length * 2); if (args.length > 0 && args[0].equals("grow")) f.set(br, newVal); for (int i = 0; i < srcBufSize; i++) br.read(); // see if the new backing array is being used if (newVal[srcBufSize - 1] == src[srcBufSize - 1]) out.format("Using new backing array, size=%d%n", newVal.length); else out.format("Using original backing array, size=%d%n", cbVal.length); // production code should handle these exceptions more gracefully } catch (FileNotFoundException x) { x.printStackTrace(); } catch (NoSuchFieldException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } catch (IOException x) { x.printStackTrace(); } } }
$ java GrowBufferedReader grow Using new backing array, size=16384 $ java GrowBufferedReader Using original backing array, size=8192
Note that the above example makes use of the array utility method java.util.Arrays.copyOf)
. java.util.Arrays
contains many methods which are convenient when operating on arrays.
Multi-dimensional arrays are simply nested arrays. A two-dimensional array is an array of arrays. A three-dimensional array is an array of two-dimensional arrays, and so on. The
example illustrates how to create and initialize a multi-dimensional array using reflection.CreateMatrix
import java.lang.reflect.Array; import static java.lang.System.out; public class CreateMatrix { public static void main(String... args) { Object matrix = Array.newInstance(int.class, 2, 2); Object row0 = Array.get(matrix, 0); Object row1 = Array.get(matrix, 1); Array.setInt(row0, 0, 1); Array.setInt(row0, 1, 2); Array.setInt(row1, 0, 3); Array.setInt(row1, 1, 4); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) out.format("matrix[%d][%d] = %d%n", i, j, ((int[][])matrix)[i][j]); } }
$ java CreateMatrix matrix[0][0] = 1 matrix[0][1] = 2 matrix[1][0] = 3 matrix[1][1] = 4
The same result could be obtained by using the following code fragment:
Object matrix = Array.newInstance(int.class, 2); Object row0 = Array.newInstance(int.class, 2); Object row1 = Array.newInstance(int.class, 2); Array.setInt(row0, 0, 1); Array.setInt(row0, 1, 2); Array.setInt(row1, 0, 3); Array.setInt(row1, 1, 4); Array.set(matrix, 0, row0); Array.set(matrix, 1, row1);
The variable argument Array.newInstance(Class<?> componentType, int... dimensions)
provides a convenient way to create multi-dimensional arrays, but the components still need to initialized using the principle that multi-dimensional arrays are nested arrays. (Reflection does not provide multiple indexed get
/set
methods for this purpose.)