1 /*
2 * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.reflect;
27
28 import jdk.internal.vm.annotation.IntrinsicCandidate;
29
30 /**
31 * The {@code Array} class provides static methods to dynamically create and
32 * access Java arrays.
33 *
34 * <p>{@code Array} permits widening conversions to occur during a get or set
35 * operation, but throws an {@code IllegalArgumentException} if a narrowing
36 * conversion would occur.
37 *
38 * @author Nakul Saraiya
39 * @since 1.1
40 */
41 public final
42 class Array {
43
44 /**
45 * Constructor. Class Array is not instantiable.
46 */
47 private Array() {}
48
49 /**
50 * Creates a new array with the specified component type and
51 * length.
52 * @implSpec
53 * Invoking this method is equivalent to creating an array
54 * as follows:
55 * <blockquote>
56 * {@code Array.newInstance(componentType, new int[]{length});}
57 * </blockquote>
58 *
59 * <p>The number of dimensions of the new array must not
60 * exceed 255.
61 *
62 * @param componentType the {@code Class} object representing the
63 * component type of the new array
64 * @param length the length of the new array
65 * @return the new array
66 * @throws NullPointerException if the specified
67 * {@code componentType} parameter is null
68 * @throws IllegalArgumentException if componentType is {@link
69 * Void#TYPE} or if the number of dimensions of the requested array
70 * instance exceed 255.
71 * @throws NegativeArraySizeException if the specified {@code length}
72 * is negative
73 */
74 public static Object newInstance(Class<?> componentType, int length)
75 throws NegativeArraySizeException {
76 return newArray(componentType, length);
77 }
78
79 /**
80 * Creates a new array
81 * with the specified component type and dimensions.
82 * If {@code componentType}
83 * represents a non-array class or interface, the new array
84 * has {@code dimensions.length} dimensions and
85 * {@code componentType} as its component type. If
86 * {@code componentType} represents an array class, the
87 * number of dimensions of the new array is equal to the sum
88 * of {@code dimensions.length} and the number of
89 * dimensions of {@code componentType}. In this case, the
90 * component type of the new array is the component type of
91 * {@code componentType}.
92 *
93 * <p>The number of dimensions of the new array must not
94 * exceed 255.
95 *
96 * @param componentType the {@code Class} object representing the component
97 * type of the new array
98 * @param dimensions an array of {@code int} representing the dimensions of
99 * the new array
100 * @return the new array
101 * @throws NullPointerException if the specified
102 * {@code componentType} argument is null
103 * @throws IllegalArgumentException if the specified {@code dimensions}
104 * argument is a zero-dimensional array, if componentType is {@link
105 * Void#TYPE}, or if the number of dimensions of the requested array
106 * instance exceed 255.
107 * @throws NegativeArraySizeException if any of the components in
108 * the specified {@code dimensions} argument is negative.
109 */
110 public static Object newInstance(Class<?> componentType, int... dimensions)
111 throws IllegalArgumentException, NegativeArraySizeException {
112 return multiNewArray(componentType, dimensions);
113 }
114
115 /**
116 * Returns the length of the specified array object, as an {@code int}.
117 *
118 * @param array the array
119 * @return the length of the array
120 * @throws IllegalArgumentException if the object argument is not
121 * an array
122 */
123 @IntrinsicCandidate
124 public static native int getLength(Object array)
125 throws IllegalArgumentException;
126
127 /**
128 * Returns the value of the indexed component in the specified
129 * array object. The value is automatically wrapped in an object
130 * if it has a primitive type.
131 *
132 * @param array the array
133 * @param index the index
134 * @return the (possibly wrapped) value of the indexed component in
135 * the specified array
136 * @throws NullPointerException If the specified object is null
137 * @throws IllegalArgumentException If the specified object is not
138 * an array
139 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
140 * argument is negative, or if it is greater than or equal to the
141 * length of the specified array
142 */
143 public static Object get(Object array, int index)
144 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
145 Class<?> componentType = array.getClass().getComponentType();
146 if (componentType != null && !componentType.isPrimitive()) {
147 Object[] objArray = (Object[]) array.getClass().cast(array);
148 return objArray[index];
149 } else {
150 return getReferenceOrPrimitive(array, index);
151 }
152 }
153
154 private static native Object getReferenceOrPrimitive(Object array, int index);
155
156 /**
157 * Returns the value of the indexed component in the specified
158 * array object, as a {@code boolean}.
159 *
160 * @param array the array
161 * @param index the index
162 * @return the value of the indexed component in the specified array
163 * @throws NullPointerException If the specified object is null
164 * @throws IllegalArgumentException If the specified object is not
165 * an array, or if the indexed element cannot be converted to the
166 * return type by an identity or widening conversion
167 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
168 * argument is negative, or if it is greater than or equal to the
169 * length of the specified array
170 * @see Array#get
171 */
172 public static native boolean getBoolean(Object array, int index)
173 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
174
175 /**
176 * Returns the value of the indexed component in the specified
177 * array object, as a {@code byte}.
178 *
179 * @param array the array
180 * @param index the index
181 * @return the value of the indexed component in the specified array
182 * @throws NullPointerException If the specified object is null
183 * @throws IllegalArgumentException If the specified object is not
184 * an array, or if the indexed element cannot be converted to the
185 * return type by an identity or widening conversion
186 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
187 * argument is negative, or if it is greater than or equal to the
188 * length of the specified array
189 * @see Array#get
190 */
191 public static native byte getByte(Object array, int index)
192 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
193
194 /**
195 * Returns the value of the indexed component in the specified
196 * array object, as a {@code char}.
197 *
198 * @param array the array
199 * @param index the index
200 * @return the value of the indexed component in the specified array
201 * @throws NullPointerException If the specified object is null
202 * @throws IllegalArgumentException If the specified object is not
203 * an array, or if the indexed element cannot be converted to the
204 * return type by an identity or widening conversion
205 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
206 * argument is negative, or if it is greater than or equal to the
207 * length of the specified array
208 * @see Array#get
209 */
210 public static native char getChar(Object array, int index)
211 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
212
213 /**
214 * Returns the value of the indexed component in the specified
215 * array object, as a {@code short}.
216 *
217 * @param array the array
218 * @param index the index
219 * @return the value of the indexed component in the specified array
220 * @throws NullPointerException If the specified object is null
221 * @throws IllegalArgumentException If the specified object is not
222 * an array, or if the indexed element cannot be converted to the
223 * return type by an identity or widening conversion
224 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
225 * argument is negative, or if it is greater than or equal to the
226 * length of the specified array
227 * @see Array#get
228 */
229 public static native short getShort(Object array, int index)
230 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
231
232 /**
233 * Returns the value of the indexed component in the specified
234 * array object, as an {@code int}.
235 *
236 * @param array the array
237 * @param index the index
238 * @return the value of the indexed component in the specified array
239 * @throws NullPointerException If the specified object is null
240 * @throws IllegalArgumentException If the specified object is not
241 * an array, or if the indexed element cannot be converted to the
242 * return type by an identity or widening conversion
243 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
244 * argument is negative, or if it is greater than or equal to the
245 * length of the specified array
246 * @see Array#get
247 */
248 public static native int getInt(Object array, int index)
249 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
250
251 /**
252 * Returns the value of the indexed component in the specified
253 * array object, as a {@code long}.
254 *
255 * @param array the array
256 * @param index the index
257 * @return the value of the indexed component in the specified array
258 * @throws NullPointerException If the specified object is null
259 * @throws IllegalArgumentException If the specified object is not
260 * an array, or if the indexed element cannot be converted to the
261 * return type by an identity or widening conversion
262 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
263 * argument is negative, or if it is greater than or equal to the
264 * length of the specified array
265 * @see Array#get
266 */
267 public static native long getLong(Object array, int index)
268 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
269
270 /**
271 * Returns the value of the indexed component in the specified
272 * array object, as a {@code float}.
273 *
274 * @param array the array
275 * @param index the index
276 * @return the value of the indexed component in the specified array
277 * @throws NullPointerException If the specified object is null
278 * @throws IllegalArgumentException If the specified object is not
279 * an array, or if the indexed element cannot be converted to the
280 * return type by an identity or widening conversion
281 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
282 * argument is negative, or if it is greater than or equal to the
283 * length of the specified array
284 * @see Array#get
285 */
286 public static native float getFloat(Object array, int index)
287 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
288
289 /**
290 * Returns the value of the indexed component in the specified
291 * array object, as a {@code double}.
292 *
293 * @param array the array
294 * @param index the index
295 * @return the value of the indexed component in the specified array
296 * @throws NullPointerException If the specified object is null
297 * @throws IllegalArgumentException If the specified object is not
298 * an array, or if the indexed element cannot be converted to the
299 * return type by an identity or widening conversion
300 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
301 * argument is negative, or if it is greater than or equal to the
302 * length of the specified array
303 * @see Array#get
304 */
305 public static native double getDouble(Object array, int index)
306 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
307
308 /**
309 * Sets the value of the indexed component of the specified array
310 * object to the specified new value. The new value is first
311 * automatically unwrapped if the array has a primitive component
312 * type.
313 * @param array the array
314 * @param index the index into the array
315 * @param value the new value of the indexed component
316 * @throws NullPointerException If the specified object argument
317 * is null
318 * @throws IllegalArgumentException If the specified object argument
319 * is not an array, or if the array component type is primitive and
320 * an unwrapping conversion fails
321 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
322 * argument is negative, or if it is greater than or equal to
323 * the length of the specified array
324 */
325 public static void set(Object array, int index, Object value)
326 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
327 Class<?> componentType = array.getClass().getComponentType();
328 if (componentType != null && !componentType.isPrimitive()) {
329 Object[] objArray = (Object[]) array.getClass().cast(array);
330 objArray[index] = componentType.cast(value);
331 } else {
332 setReferenceOrPrimitive(array, index, value);
333 }
334 }
335
336 private static native void setReferenceOrPrimitive(Object array, int index, Object value);
337
338 /**
339 * Sets the value of the indexed component of the specified array
340 * object to the specified {@code boolean} value.
341 * @param array the array
342 * @param index the index into the array
343 * @param z the new value of the indexed component
344 * @throws NullPointerException If the specified object argument
345 * is null
346 * @throws IllegalArgumentException If the specified object argument
347 * is not an array, or if the specified value cannot be converted
348 * to the underlying array's component type by an identity or a
349 * primitive widening conversion
350 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
351 * argument is negative, or if it is greater than or equal to
352 * the length of the specified array
353 * @see Array#set
354 */
355 public static native void setBoolean(Object array, int index, boolean z)
356 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
357
358 /**
359 * Sets the value of the indexed component of the specified array
360 * object to the specified {@code byte} value.
361 * @param array the array
362 * @param index the index into the array
363 * @param b the new value of the indexed component
364 * @throws NullPointerException If the specified object argument
365 * is null
366 * @throws IllegalArgumentException If the specified object argument
367 * is not an array, or if the specified value cannot be converted
368 * to the underlying array's component type by an identity or a
369 * primitive widening conversion
370 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
371 * argument is negative, or if it is greater than or equal to
372 * the length of the specified array
373 * @see Array#set
374 */
375 public static native void setByte(Object array, int index, byte b)
376 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
377
378 /**
379 * Sets the value of the indexed component of the specified array
380 * object to the specified {@code char} value.
381 * @param array the array
382 * @param index the index into the array
383 * @param c the new value of the indexed component
384 * @throws NullPointerException If the specified object argument
385 * is null
386 * @throws IllegalArgumentException If the specified object argument
387 * is not an array, or if the specified value cannot be converted
388 * to the underlying array's component type by an identity or a
389 * primitive widening conversion
390 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
391 * argument is negative, or if it is greater than or equal to
392 * the length of the specified array
393 * @see Array#set
394 */
395 public static native void setChar(Object array, int index, char c)
396 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
397
398 /**
399 * Sets the value of the indexed component of the specified array
400 * object to the specified {@code short} value.
401 * @param array the array
402 * @param index the index into the array
403 * @param s the new value of the indexed component
404 * @throws NullPointerException If the specified object argument
405 * is null
406 * @throws IllegalArgumentException If the specified object argument
407 * is not an array, or if the specified value cannot be converted
408 * to the underlying array's component type by an identity or a
409 * primitive widening conversion
410 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
411 * argument is negative, or if it is greater than or equal to
412 * the length of the specified array
413 * @see Array#set
414 */
415 public static native void setShort(Object array, int index, short s)
416 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
417
418 /**
419 * Sets the value of the indexed component of the specified array
420 * object to the specified {@code int} value.
421 * @param array the array
422 * @param index the index into the array
423 * @param i the new value of the indexed component
424 * @throws NullPointerException If the specified object argument
425 * is null
426 * @throws IllegalArgumentException If the specified object argument
427 * is not an array, or if the specified value cannot be converted
428 * to the underlying array's component type by an identity or a
429 * primitive widening conversion
430 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
431 * argument is negative, or if it is greater than or equal to
432 * the length of the specified array
433 * @see Array#set
434 */
435 public static native void setInt(Object array, int index, int i)
436 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
437
438 /**
439 * Sets the value of the indexed component of the specified array
440 * object to the specified {@code long} value.
441 * @param array the array
442 * @param index the index into the array
443 * @param l the new value of the indexed component
444 * @throws NullPointerException If the specified object argument
445 * is null
446 * @throws IllegalArgumentException If the specified object argument
447 * is not an array, or if the specified value cannot be converted
448 * to the underlying array's component type by an identity or a
449 * primitive widening conversion
450 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
451 * argument is negative, or if it is greater than or equal to
452 * the length of the specified array
453 * @see Array#set
454 */
455 public static native void setLong(Object array, int index, long l)
456 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
457
458 /**
459 * Sets the value of the indexed component of the specified array
460 * object to the specified {@code float} value.
461 * @param array the array
462 * @param index the index into the array
463 * @param f the new value of the indexed component
464 * @throws NullPointerException If the specified object argument
465 * is null
466 * @throws IllegalArgumentException If the specified object argument
467 * is not an array, or if the specified value cannot be converted
468 * to the underlying array's component type by an identity or a
469 * primitive widening conversion
470 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
471 * argument is negative, or if it is greater than or equal to
472 * the length of the specified array
473 * @see Array#set
474 */
475 public static native void setFloat(Object array, int index, float f)
476 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
477
478 /**
479 * Sets the value of the indexed component of the specified array
480 * object to the specified {@code double} value.
481 * @param array the array
482 * @param index the index into the array
483 * @param d the new value of the indexed component
484 * @throws NullPointerException If the specified object argument
485 * is null
486 * @throws IllegalArgumentException If the specified object argument
487 * is not an array, or if the specified value cannot be converted
488 * to the underlying array's component type by an identity or a
489 * primitive widening conversion
490 * @throws ArrayIndexOutOfBoundsException If the specified {@code index}
491 * argument is negative, or if it is greater than or equal to
492 * the length of the specified array
493 * @see Array#set
494 */
495 public static native void setDouble(Object array, int index, double d)
496 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
497
498 /*
499 * Private
500 */
501
502 @IntrinsicCandidate
503 private static native Object newArray(Class<?> componentType, int length)
504 throws NegativeArraySizeException;
505
506 private static native Object multiNewArray(Class<?> componentType,
507 int[] dimensions)
508 throws IllegalArgumentException, NegativeArraySizeException;
509
510
511 }