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 native Object get(Object array, int index)
144         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
145 
146     /**
147      * Returns the value of the indexed component in the specified
148      * array object, as a {@code boolean}.
149      *
150      * @param array the array
151      * @param index the index
152      * @return the value of the indexed component in the specified array
153      * @throws    NullPointerException If the specified object is null
154      * @throws    IllegalArgumentException If the specified object is not
155      * an array, or if the indexed element cannot be converted to the
156      * return type by an identity or widening conversion
157      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
158      * argument is negative, or if it is greater than or equal to the
159      * length of the specified array
160      * @see Array#get
161      */
162     public static native boolean getBoolean(Object array, int index)
163         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
164 
165     /**
166      * Returns the value of the indexed component in the specified
167      * array object, as a {@code byte}.
168      *
169      * @param array the array
170      * @param index the index
171      * @return the value of the indexed component in the specified array
172      * @throws    NullPointerException If the specified object is null
173      * @throws    IllegalArgumentException If the specified object is not
174      * an array, or if the indexed element cannot be converted to the
175      * return type by an identity or widening conversion
176      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
177      * argument is negative, or if it is greater than or equal to the
178      * length of the specified array
179      * @see Array#get
180      */
181     public static native byte getByte(Object array, int index)
182         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
183 
184     /**
185      * Returns the value of the indexed component in the specified
186      * array object, as a {@code char}.
187      *
188      * @param array the array
189      * @param index the index
190      * @return the value of the indexed component in the specified array
191      * @throws    NullPointerException If the specified object is null
192      * @throws    IllegalArgumentException If the specified object is not
193      * an array, or if the indexed element cannot be converted to the
194      * return type by an identity or widening conversion
195      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
196      * argument is negative, or if it is greater than or equal to the
197      * length of the specified array
198      * @see Array#get
199      */
200     public static native char getChar(Object array, int index)
201         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
202 
203     /**
204      * Returns the value of the indexed component in the specified
205      * array object, as a {@code short}.
206      *
207      * @param array the array
208      * @param index the index
209      * @return the value of the indexed component in the specified array
210      * @throws    NullPointerException If the specified object is null
211      * @throws    IllegalArgumentException If the specified object is not
212      * an array, or if the indexed element cannot be converted to the
213      * return type by an identity or widening conversion
214      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
215      * argument is negative, or if it is greater than or equal to the
216      * length of the specified array
217      * @see Array#get
218      */
219     public static native short getShort(Object array, int index)
220         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
221 
222     /**
223      * Returns the value of the indexed component in the specified
224      * array object, as an {@code int}.
225      *
226      * @param array the array
227      * @param index the index
228      * @return the value of the indexed component in the specified array
229      * @throws    NullPointerException If the specified object is null
230      * @throws    IllegalArgumentException If the specified object is not
231      * an array, or if the indexed element cannot be converted to the
232      * return type by an identity or widening conversion
233      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
234      * argument is negative, or if it is greater than or equal to the
235      * length of the specified array
236      * @see Array#get
237      */
238     public static native int getInt(Object array, int index)
239         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
240 
241     /**
242      * Returns the value of the indexed component in the specified
243      * array object, as a {@code long}.
244      *
245      * @param array the array
246      * @param index the index
247      * @return the value of the indexed component in the specified array
248      * @throws    NullPointerException If the specified object is null
249      * @throws    IllegalArgumentException If the specified object is not
250      * an array, or if the indexed element cannot be converted to the
251      * return type by an identity or widening conversion
252      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
253      * argument is negative, or if it is greater than or equal to the
254      * length of the specified array
255      * @see Array#get
256      */
257     public static native long getLong(Object array, int index)
258         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
259 
260     /**
261      * Returns the value of the indexed component in the specified
262      * array object, as a {@code float}.
263      *
264      * @param array the array
265      * @param index the index
266      * @return the value of the indexed component in the specified array
267      * @throws    NullPointerException If the specified object is null
268      * @throws    IllegalArgumentException If the specified object is not
269      * an array, or if the indexed element cannot be converted to the
270      * return type by an identity or widening conversion
271      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
272      * argument is negative, or if it is greater than or equal to the
273      * length of the specified array
274      * @see Array#get
275      */
276     public static native float getFloat(Object array, int index)
277         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
278 
279     /**
280      * Returns the value of the indexed component in the specified
281      * array object, as a {@code double}.
282      *
283      * @param array the array
284      * @param index the index
285      * @return the value of the indexed component in the specified array
286      * @throws    NullPointerException If the specified object is null
287      * @throws    IllegalArgumentException If the specified object is not
288      * an array, or if the indexed element cannot be converted to the
289      * return type by an identity or widening conversion
290      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
291      * argument is negative, or if it is greater than or equal to the
292      * length of the specified array
293      * @see Array#get
294      */
295     public static native double getDouble(Object array, int index)
296         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
297 
298     /**
299      * Sets the value of the indexed component of the specified array
300      * object to the specified new value.  The new value is first
301      * automatically unwrapped if the array has a primitive component
302      * type.
303      * @param array the array
304      * @param index the index into the array
305      * @param value the new value of the indexed component
306      * @throws    NullPointerException If the specified object argument
307      * is null
308      * @throws    IllegalArgumentException If the specified object argument
309      * is not an array, or if the array component type is primitive and
310      * an unwrapping conversion fails
311      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
312      * argument is negative, or if it is greater than or equal to
313      * the length of the specified array
314      */
315     public static native void set(Object array, int index, Object value)
316         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
317 
318     /**
319      * Sets the value of the indexed component of the specified array
320      * object to the specified {@code boolean} value.
321      * @param array the array
322      * @param index the index into the array
323      * @param z the new value of the indexed component
324      * @throws    NullPointerException If the specified object argument
325      * is null
326      * @throws    IllegalArgumentException If the specified object argument
327      * is not an array, or if the specified value cannot be converted
328      * to the underlying array's component type by an identity or a
329      * primitive widening conversion
330      * @throws    ArrayIndexOutOfBoundsException If the specified {@code index}
331      * argument is negative, or if it is greater than or equal to
332      * the length of the specified array
333      * @see Array#set
334      */
335     public static native void setBoolean(Object array, int index, boolean z)
336         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
337 
338     /**
339      * Sets the value of the indexed component of the specified array
340      * object to the specified {@code byte} value.
341      * @param array the array
342      * @param index the index into the array
343      * @param b 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 setByte(Object array, int index, byte b)
356         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
357 
358     /**
359      * Sets the value of the indexed component of the specified array
360      * object to the specified {@code char} value.
361      * @param array the array
362      * @param index the index into the array
363      * @param c 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 setChar(Object array, int index, char c)
376         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
377 
378     /**
379      * Sets the value of the indexed component of the specified array
380      * object to the specified {@code short} value.
381      * @param array the array
382      * @param index the index into the array
383      * @param s 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 setShort(Object array, int index, short s)
396         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
397 
398     /**
399      * Sets the value of the indexed component of the specified array
400      * object to the specified {@code int} value.
401      * @param array the array
402      * @param index the index into the array
403      * @param i 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 setInt(Object array, int index, int i)
416         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
417 
418     /**
419      * Sets the value of the indexed component of the specified array
420      * object to the specified {@code long} value.
421      * @param array the array
422      * @param index the index into the array
423      * @param l 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 setLong(Object array, int index, long l)
436         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
437 
438     /**
439      * Sets the value of the indexed component of the specified array
440      * object to the specified {@code float} value.
441      * @param array the array
442      * @param index the index into the array
443      * @param f 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 setFloat(Object array, int index, float f)
456         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
457 
458     /**
459      * Sets the value of the indexed component of the specified array
460      * object to the specified {@code double} value.
461      * @param array the array
462      * @param index the index into the array
463      * @param d 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 setDouble(Object array, int index, double d)
476         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
477 
478     /*
479      * Private
480      */
481 
482     @IntrinsicCandidate
483     private static native Object newArray(Class<?> componentType, int length)
484         throws NegativeArraySizeException;
485 
486     private static native Object multiNewArray(Class<?> componentType,
487         int[] dimensions)
488         throws IllegalArgumentException, NegativeArraySizeException;
489 
490 
491 }