2 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
26 package java.lang.reflect;
28 import org.apidesign.bck2brwsr.core.JavaScriptBody;
29 import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
32 * The {@code Array} class provides static methods to dynamically create and
35 * <p>{@code Array} permits widening conversions to occur during a get or set
36 * operation, but throws an {@code IllegalArgumentException} if a narrowing
37 * conversion would occur.
39 * @author Nakul Saraiya
41 @JavaScriptPrototype(prototype = "new Array", container = "Array.prototype")
46 * Constructor. Class Array is not instantiable.
51 * Creates a new array with the specified component type and
53 * Invoking this method is equivalent to creating an array
58 * Array.newInstance(componentType, x);
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 * @exception NullPointerException if the specified
67 * {@code componentType} parameter is null
68 * @exception IllegalArgumentException if componentType is {@link Void#TYPE}
69 * @exception NegativeArraySizeException if the specified {@code length}
72 public static Object newInstance(Class<?> componentType, int length)
73 throws NegativeArraySizeException {
75 throw new NegativeArraySizeException();
77 String sig = findSignature(componentType);
78 return newArray(componentType.isPrimitive(), sig, length);
81 private static String findSignature(Class<?> type) {
82 if (type == Integer.TYPE) {
85 if (type == Long.TYPE) {
88 if (type == Double.TYPE) {
91 if (type == Float.TYPE) {
94 if (type == Byte.TYPE) {
97 if (type == Boolean.TYPE) {
100 if (type == Short.TYPE) {
103 if (type == Character.TYPE) {
106 if (type.getName().equals("void")) {
107 throw new IllegalStateException("Can't create array for " + type);
109 return "[L" + type.getName() + ";";
112 * Creates a new array
113 * with the specified component type and dimensions.
114 * If {@code componentType}
115 * represents a non-array class or interface, the new array
116 * has {@code dimensions.length} dimensions and
117 * {@code componentType} as its component type. If
118 * {@code componentType} represents an array class, the
119 * number of dimensions of the new array is equal to the sum
120 * of {@code dimensions.length} and the number of
121 * dimensions of {@code componentType}. In this case, the
122 * component type of the new array is the component type of
123 * {@code componentType}.
125 * <p>The number of dimensions of the new array must not
126 * exceed the number of array dimensions supported by the
127 * implementation (typically 255).
129 * @param componentType the {@code Class} object representing the component
130 * type of the new array
131 * @param dimensions an array of {@code int} representing the dimensions of
133 * @return the new array
134 * @exception NullPointerException if the specified
135 * {@code componentType} argument is null
136 * @exception IllegalArgumentException if the specified {@code dimensions}
137 * argument is a zero-dimensional array, or if the number of
138 * requested dimensions exceeds the limit on the number of array dimensions
139 * supported by the implementation (typically 255), or if componentType
140 * is {@link Void#TYPE}.
141 * @exception NegativeArraySizeException if any of the components in
142 * the specified {@code dimensions} argument is negative.
144 public static Object newInstance(Class<?> componentType, int... dimensions)
145 throws IllegalArgumentException, NegativeArraySizeException {
146 StringBuilder sig = new StringBuilder();
147 for (int i = 1; i < dimensions.length; i++) {
150 sig.append(findSignature(componentType));
151 return multiNewArray(sig.toString(), dimensions, 0);
155 * Returns the length of the specified array object, as an {@code int}.
157 * @param array the array
158 * @return the length of the array
159 * @exception IllegalArgumentException if the object argument is not
162 public static int getLength(Object array)
163 throws IllegalArgumentException {
164 if (!array.getClass().isArray()) {
165 throw new IllegalArgumentException("Argument is not an array");
167 return length(array);
170 @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
171 private static native int length(Object arr);
174 * Returns the value of the indexed component in the specified
175 * array object. The value is automatically wrapped in an object
176 * if it has a primitive type.
178 * @param array the array
179 * @param index the index
180 * @return the (possibly wrapped) value of the indexed component in
181 * the specified array
182 * @exception NullPointerException If the specified object is null
183 * @exception IllegalArgumentException If the specified object is not
185 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
186 * argument is negative, or if it is greater than or equal to the
187 * length of the specified array
189 public static native Object get(Object array, int index)
190 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
193 * Returns the value of the indexed component in the specified
194 * array object, as a {@code boolean}.
196 * @param array the array
197 * @param index the index
198 * @return the value of the indexed component in the specified array
199 * @exception NullPointerException If the specified object is null
200 * @exception IllegalArgumentException If the specified object is not
201 * an array, or if the indexed element cannot be converted to the
202 * return type by an identity or widening conversion
203 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
204 * argument is negative, or if it is greater than or equal to the
205 * length of the specified array
208 public static native boolean getBoolean(Object array, int index)
209 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
212 * Returns the value of the indexed component in the specified
213 * array object, as a {@code byte}.
215 * @param array the array
216 * @param index the index
217 * @return the value of the indexed component in the specified array
218 * @exception NullPointerException If the specified object is null
219 * @exception IllegalArgumentException If the specified object is not
220 * an array, or if the indexed element cannot be converted to the
221 * return type by an identity or widening conversion
222 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
223 * argument is negative, or if it is greater than or equal to the
224 * length of the specified array
227 public static byte getByte(Object array, int index)
228 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
229 if (array.getClass().getComponentType() != Byte.TYPE) {
230 throw new IllegalArgumentException();
232 byte[] arr = (byte[]) array;
237 * Returns the value of the indexed component in the specified
238 * array object, as a {@code char}.
240 * @param array the array
241 * @param index the index
242 * @return the value of the indexed component in the specified array
243 * @exception NullPointerException If the specified object is null
244 * @exception IllegalArgumentException If the specified object is not
245 * an array, or if the indexed element cannot be converted to the
246 * return type by an identity or widening conversion
247 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
248 * argument is negative, or if it is greater than or equal to the
249 * length of the specified array
252 public static native char getChar(Object array, int index)
253 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
256 * Returns the value of the indexed component in the specified
257 * array object, as a {@code short}.
259 * @param array the array
260 * @param index the index
261 * @return the value of the indexed component in the specified array
262 * @exception NullPointerException If the specified object is null
263 * @exception IllegalArgumentException If the specified object is not
264 * an array, or if the indexed element cannot be converted to the
265 * return type by an identity or widening conversion
266 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
267 * argument is negative, or if it is greater than or equal to the
268 * length of the specified array
271 public static short getShort(Object array, int index)
272 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
273 final Class<?> t = array.getClass().getComponentType();
274 if (t == Short.TYPE) {
275 short[] arr = (short[]) array;
278 return getByte(array, index);
282 * Returns the value of the indexed component in the specified
283 * array object, as an {@code int}.
285 * @param array the array
286 * @param index the index
287 * @return the value of the indexed component in the specified array
288 * @exception NullPointerException If the specified object is null
289 * @exception IllegalArgumentException If the specified object is not
290 * an array, or if the indexed element cannot be converted to the
291 * return type by an identity or widening conversion
292 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
293 * argument is negative, or if it is greater than or equal to the
294 * length of the specified array
297 public static int getInt(Object array, int index)
298 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
299 final Class<?> t = array.getClass().getComponentType();
300 if (t == Integer.TYPE) {
301 int[] arr = (int[]) array;
304 return getShort(array, index);
308 * Returns the value of the indexed component in the specified
309 * array object, as a {@code long}.
311 * @param array the array
312 * @param index the index
313 * @return the value of the indexed component in the specified array
314 * @exception NullPointerException If the specified object is null
315 * @exception IllegalArgumentException If the specified object is not
316 * an array, or if the indexed element cannot be converted to the
317 * return type by an identity or widening conversion
318 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
319 * argument is negative, or if it is greater than or equal to the
320 * length of the specified array
323 public static long getLong(Object array, int index)
324 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
325 final Class<?> t = array.getClass().getComponentType();
326 if (t == Long.TYPE) {
327 long[] arr = (long[]) array;
330 return getInt(array, index);
334 * Returns the value of the indexed component in the specified
335 * array object, as a {@code float}.
337 * @param array the array
338 * @param index the index
339 * @return the value of the indexed component in the specified array
340 * @exception NullPointerException If the specified object is null
341 * @exception IllegalArgumentException If the specified object is not
342 * an array, or if the indexed element cannot be converted to the
343 * return type by an identity or widening conversion
344 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
345 * argument is negative, or if it is greater than or equal to the
346 * length of the specified array
349 public static float getFloat(Object array, int index)
350 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
351 final Class<?> t = array.getClass().getComponentType();
352 if (t == Float.TYPE) {
353 float[] arr = (float[]) array;
356 return getLong(array, index);
360 * Returns the value of the indexed component in the specified
361 * array object, as a {@code double}.
363 * @param array the array
364 * @param index the index
365 * @return the value of the indexed component in the specified array
366 * @exception NullPointerException If the specified object is null
367 * @exception IllegalArgumentException If the specified object is not
368 * an array, or if the indexed element cannot be converted to the
369 * return type by an identity or widening conversion
370 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
371 * argument is negative, or if it is greater than or equal to the
372 * length of the specified array
375 public static double getDouble(Object array, int index)
376 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
377 final Class<?> t = array.getClass().getComponentType();
378 if (t == Double.TYPE) {
379 double[] arr = (double[]) array;
382 return getFloat(array, index);
386 * Sets the value of the indexed component of the specified array
387 * object to the specified new value. The new value is first
388 * automatically unwrapped if the array has a primitive component
390 * @param array the array
391 * @param index the index into the array
392 * @param value the new value of the indexed component
393 * @exception NullPointerException If the specified object argument
395 * @exception IllegalArgumentException If the specified object argument
396 * is not an array, or if the array component type is primitive and
397 * an unwrapping conversion fails
398 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
399 * argument is negative, or if it is greater than or equal to
400 * the length of the specified array
402 public static native void set(Object array, int index, Object value)
403 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
406 * Sets the value of the indexed component of the specified array
407 * object to the specified {@code boolean} value.
408 * @param array the array
409 * @param index the index into the array
410 * @param z the new value of the indexed component
411 * @exception NullPointerException If the specified object argument
413 * @exception IllegalArgumentException If the specified object argument
414 * is not an array, or if the specified value cannot be converted
415 * to the underlying array's component type by an identity or a
416 * primitive widening conversion
417 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
418 * argument is negative, or if it is greater than or equal to
419 * the length of the specified array
422 public static native void setBoolean(Object array, int index, boolean z)
423 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
426 * Sets the value of the indexed component of the specified array
427 * object to the specified {@code byte} value.
428 * @param array the array
429 * @param index the index into the array
430 * @param b the new value of the indexed component
431 * @exception NullPointerException If the specified object argument
433 * @exception IllegalArgumentException If the specified object argument
434 * is not an array, or if the specified value cannot be converted
435 * to the underlying array's component type by an identity or a
436 * primitive widening conversion
437 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
438 * argument is negative, or if it is greater than or equal to
439 * the length of the specified array
442 public static void setByte(Object array, int index, byte b)
443 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
444 Class<?> t = array.getClass().getComponentType();
445 if (t == Byte.TYPE) {
446 byte[] arr = (byte[]) array;
449 setShort(array, index, b);
454 * Sets the value of the indexed component of the specified array
455 * object to the specified {@code char} value.
456 * @param array the array
457 * @param index the index into the array
458 * @param c the new value of the indexed component
459 * @exception NullPointerException If the specified object argument
461 * @exception IllegalArgumentException If the specified object argument
462 * is not an array, or if the specified value cannot be converted
463 * to the underlying array's component type by an identity or a
464 * primitive widening conversion
465 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
466 * argument is negative, or if it is greater than or equal to
467 * the length of the specified array
470 public static native void setChar(Object array, int index, char c)
471 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
474 * Sets the value of the indexed component of the specified array
475 * object to the specified {@code short} value.
476 * @param array the array
477 * @param index the index into the array
478 * @param s the new value of the indexed component
479 * @exception NullPointerException If the specified object argument
481 * @exception IllegalArgumentException If the specified object argument
482 * is not an array, or if the specified value cannot be converted
483 * to the underlying array's component type by an identity or a
484 * primitive widening conversion
485 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
486 * argument is negative, or if it is greater than or equal to
487 * the length of the specified array
490 public static void setShort(Object array, int index, short s)
491 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
492 Class<?> t = array.getClass().getComponentType();
493 if (t == Short.TYPE) {
494 short[] arr = (short[]) array;
497 setInt(array, index, s);
503 * Sets the value of the indexed component of the specified array
504 * object to the specified {@code int} value.
505 * @param array the array
506 * @param index the index into the array
507 * @param i the new value of the indexed component
508 * @exception NullPointerException If the specified object argument
510 * @exception IllegalArgumentException If the specified object argument
511 * is not an array, or if the specified value cannot be converted
512 * to the underlying array's component type by an identity or a
513 * primitive widening conversion
514 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
515 * argument is negative, or if it is greater than or equal to
516 * the length of the specified array
519 public static void setInt(Object array, int index, int i)
520 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
521 Class<?> t = array.getClass().getComponentType();
522 if (t == Integer.TYPE) {
523 long[] arr = (long[]) array;
526 setLong(array, index, i);
531 * Sets the value of the indexed component of the specified array
532 * object to the specified {@code long} value.
533 * @param array the array
534 * @param index the index into the array
535 * @param l the new value of the indexed component
536 * @exception NullPointerException If the specified object argument
538 * @exception IllegalArgumentException If the specified object argument
539 * is not an array, or if the specified value cannot be converted
540 * to the underlying array's component type by an identity or a
541 * primitive widening conversion
542 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
543 * argument is negative, or if it is greater than or equal to
544 * the length of the specified array
547 public static void setLong(Object array, int index, long l)
548 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
549 Class<?> t = array.getClass().getComponentType();
550 if (t == Long.TYPE) {
551 long[] arr = (long[]) array;
554 setFloat(array, index, l);
559 * Sets the value of the indexed component of the specified array
560 * object to the specified {@code float} value.
561 * @param array the array
562 * @param index the index into the array
563 * @param f the new value of the indexed component
564 * @exception NullPointerException If the specified object argument
566 * @exception IllegalArgumentException If the specified object argument
567 * is not an array, or if the specified value cannot be converted
568 * to the underlying array's component type by an identity or a
569 * primitive widening conversion
570 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
571 * argument is negative, or if it is greater than or equal to
572 * the length of the specified array
575 public static void setFloat(Object array, int index, float f)
576 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
577 Class<?> t = array.getClass().getComponentType();
578 if (t == Float.TYPE) {
579 float[] arr = (float[])array;
582 setDouble(array, index, f);
587 * Sets the value of the indexed component of the specified array
588 * object to the specified {@code double} value.
589 * @param array the array
590 * @param index the index into the array
591 * @param d the new value of the indexed component
592 * @exception NullPointerException If the specified object argument
594 * @exception IllegalArgumentException If the specified object argument
595 * is not an array, or if the specified value cannot be converted
596 * to the underlying array's component type by an identity or a
597 * primitive widening conversion
598 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
599 * argument is negative, or if it is greater than or equal to
600 * the length of the specified array
603 public static void setDouble(Object array, int index, double d)
604 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
605 Class<?> t = array.getClass().getComponentType();
606 if (t == Double.TYPE) {
607 double[] arr = (double[])array;
610 throw new IllegalArgumentException("argument type mismatch");
618 @JavaScriptBody(args = { "primitive", "sig", "length" }, body =
619 "var arr = new Array(length);\n"
620 + "var value = primitive ? 0 : null;\n"
621 + "for(var i = 0; i < length; i++) arr[i] = value;\n"
622 + "arr.jvmName = sig;\n"
625 private static native Object newArray(boolean primitive, String sig, int length);
627 private static Object multiNewArray(String sig, int[] dims, int index)
628 throws IllegalArgumentException, NegativeArraySizeException {
629 if (dims.length == index + 1) {
630 return newArray(sig.length() == 2, sig, dims[index]);
632 Object[] arr = (Object[]) newArray(false, sig, dims[index]);
633 String compsig = sig.substring(1);
634 for (int i = 0; i < arr.length; i++) {
635 arr[i] = multiNewArray(compsig, dims, index + 1);