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 Object get(Object array, int index)
190 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
191 final Class<?> t = array.getClass().getComponentType();
192 if (t.isPrimitive()) {
193 return fromPrimitive(t, array, index);
195 return ((Object[])array)[index];
200 * Returns the value of the indexed component in the specified
201 * array object, as a {@code boolean}.
203 * @param array the array
204 * @param index the index
205 * @return the value of the indexed component in the specified array
206 * @exception NullPointerException If the specified object is null
207 * @exception IllegalArgumentException If the specified object is not
208 * an array, or if the indexed element cannot be converted to the
209 * return type by an identity or widening conversion
210 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
211 * argument is negative, or if it is greater than or equal to the
212 * length of the specified array
215 public static native boolean getBoolean(Object array, int index)
216 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
219 * Returns the value of the indexed component in the specified
220 * array object, as a {@code byte}.
222 * @param array the array
223 * @param index the index
224 * @return the value of the indexed component in the specified array
225 * @exception NullPointerException If the specified object is null
226 * @exception IllegalArgumentException If the specified object is not
227 * an array, or if the indexed element cannot be converted to the
228 * return type by an identity or widening conversion
229 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
230 * argument is negative, or if it is greater than or equal to the
231 * length of the specified array
234 public static byte getByte(Object array, int index)
235 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
236 if (array.getClass().getComponentType() != Byte.TYPE) {
237 throw new IllegalArgumentException();
239 byte[] arr = (byte[]) array;
244 * Returns the value of the indexed component in the specified
245 * array object, as a {@code char}.
247 * @param array the array
248 * @param index the index
249 * @return the value of the indexed component in the specified array
250 * @exception NullPointerException If the specified object is null
251 * @exception IllegalArgumentException If the specified object is not
252 * an array, or if the indexed element cannot be converted to the
253 * return type by an identity or widening conversion
254 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
255 * argument is negative, or if it is greater than or equal to the
256 * length of the specified array
259 public static native char getChar(Object array, int index)
260 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
263 * Returns the value of the indexed component in the specified
264 * array object, as a {@code short}.
266 * @param array the array
267 * @param index the index
268 * @return the value of the indexed component in the specified array
269 * @exception NullPointerException If the specified object is null
270 * @exception IllegalArgumentException If the specified object is not
271 * an array, or if the indexed element cannot be converted to the
272 * return type by an identity or widening conversion
273 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
274 * argument is negative, or if it is greater than or equal to the
275 * length of the specified array
278 public static short getShort(Object array, int index)
279 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
280 final Class<?> t = array.getClass().getComponentType();
281 if (t == Short.TYPE) {
282 short[] arr = (short[]) array;
285 return getByte(array, index);
289 * Returns the value of the indexed component in the specified
290 * array object, as an {@code int}.
292 * @param array the array
293 * @param index the index
294 * @return the value of the indexed component in the specified array
295 * @exception NullPointerException If the specified object is null
296 * @exception IllegalArgumentException If the specified object is not
297 * an array, or if the indexed element cannot be converted to the
298 * return type by an identity or widening conversion
299 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
300 * argument is negative, or if it is greater than or equal to the
301 * length of the specified array
304 public static int getInt(Object array, int index)
305 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
306 final Class<?> t = array.getClass().getComponentType();
307 if (t == Integer.TYPE) {
308 int[] arr = (int[]) array;
311 return getShort(array, index);
315 * Returns the value of the indexed component in the specified
316 * array object, as a {@code long}.
318 * @param array the array
319 * @param index the index
320 * @return the value of the indexed component in the specified array
321 * @exception NullPointerException If the specified object is null
322 * @exception IllegalArgumentException If the specified object is not
323 * an array, or if the indexed element cannot be converted to the
324 * return type by an identity or widening conversion
325 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
326 * argument is negative, or if it is greater than or equal to the
327 * length of the specified array
330 public static long getLong(Object array, int index)
331 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
332 final Class<?> t = array.getClass().getComponentType();
333 if (t == Long.TYPE) {
334 long[] arr = (long[]) array;
337 return getInt(array, index);
341 * Returns the value of the indexed component in the specified
342 * array object, as a {@code float}.
344 * @param array the array
345 * @param index the index
346 * @return the value of the indexed component in the specified array
347 * @exception NullPointerException If the specified object is null
348 * @exception IllegalArgumentException If the specified object is not
349 * an array, or if the indexed element cannot be converted to the
350 * return type by an identity or widening conversion
351 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
352 * argument is negative, or if it is greater than or equal to the
353 * length of the specified array
356 public static float getFloat(Object array, int index)
357 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
358 final Class<?> t = array.getClass().getComponentType();
359 if (t == Float.TYPE) {
360 float[] arr = (float[]) array;
363 return getLong(array, index);
367 * Returns the value of the indexed component in the specified
368 * array object, as a {@code double}.
370 * @param array the array
371 * @param index the index
372 * @return the value of the indexed component in the specified array
373 * @exception NullPointerException If the specified object is null
374 * @exception IllegalArgumentException If the specified object is not
375 * an array, or if the indexed element cannot be converted to the
376 * return type by an identity or widening conversion
377 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
378 * argument is negative, or if it is greater than or equal to the
379 * length of the specified array
382 public static double getDouble(Object array, int index)
383 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
384 final Class<?> t = array.getClass().getComponentType();
385 if (t == Double.TYPE) {
386 double[] arr = (double[]) array;
389 return getFloat(array, index);
393 * Sets the value of the indexed component of the specified array
394 * object to the specified new value. The new value is first
395 * automatically unwrapped if the array has a primitive component
397 * @param array the array
398 * @param index the index into the array
399 * @param value the new value of the indexed component
400 * @exception NullPointerException If the specified object argument
402 * @exception IllegalArgumentException If the specified object argument
403 * is not an array, or if the array component type is primitive and
404 * an unwrapping conversion fails
405 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
406 * argument is negative, or if it is greater than or equal to
407 * the length of the specified array
409 public static void set(Object array, int index, Object value)
410 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
411 if (array.getClass().getComponentType().isPrimitive()) {
412 throw new IllegalArgumentException();
414 Object[] arr = (Object[])array;
420 * Sets the value of the indexed component of the specified array
421 * object to the specified {@code boolean} value.
422 * @param array the array
423 * @param index the index into the array
424 * @param z the new value of the indexed component
425 * @exception NullPointerException If the specified object argument
427 * @exception IllegalArgumentException If the specified object argument
428 * is not an array, or if the specified value cannot be converted
429 * to the underlying array's component type by an identity or a
430 * primitive widening conversion
431 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
432 * argument is negative, or if it is greater than or equal to
433 * the length of the specified array
436 public static native void setBoolean(Object array, int index, boolean z)
437 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
440 * Sets the value of the indexed component of the specified array
441 * object to the specified {@code byte} value.
442 * @param array the array
443 * @param index the index into the array
444 * @param b the new value of the indexed component
445 * @exception NullPointerException If the specified object argument
447 * @exception IllegalArgumentException If the specified object argument
448 * is not an array, or if the specified value cannot be converted
449 * to the underlying array's component type by an identity or a
450 * primitive widening conversion
451 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
452 * argument is negative, or if it is greater than or equal to
453 * the length of the specified array
456 public static void setByte(Object array, int index, byte b)
457 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
458 Class<?> t = array.getClass().getComponentType();
459 if (t == Byte.TYPE) {
460 byte[] arr = (byte[]) array;
463 setShort(array, index, b);
468 * Sets the value of the indexed component of the specified array
469 * object to the specified {@code char} value.
470 * @param array the array
471 * @param index the index into the array
472 * @param c the new value of the indexed component
473 * @exception NullPointerException If the specified object argument
475 * @exception IllegalArgumentException If the specified object argument
476 * is not an array, or if the specified value cannot be converted
477 * to the underlying array's component type by an identity or a
478 * primitive widening conversion
479 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
480 * argument is negative, or if it is greater than or equal to
481 * the length of the specified array
484 public static native void setChar(Object array, int index, char c)
485 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
488 * Sets the value of the indexed component of the specified array
489 * object to the specified {@code short} value.
490 * @param array the array
491 * @param index the index into the array
492 * @param s the new value of the indexed component
493 * @exception NullPointerException If the specified object argument
495 * @exception IllegalArgumentException If the specified object argument
496 * is not an array, or if the specified value cannot be converted
497 * to the underlying array's component type by an identity or a
498 * primitive widening conversion
499 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
500 * argument is negative, or if it is greater than or equal to
501 * the length of the specified array
504 public static void setShort(Object array, int index, short s)
505 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
506 Class<?> t = array.getClass().getComponentType();
507 if (t == Short.TYPE) {
508 short[] arr = (short[]) array;
511 setInt(array, index, s);
517 * Sets the value of the indexed component of the specified array
518 * object to the specified {@code int} value.
519 * @param array the array
520 * @param index the index into the array
521 * @param i the new value of the indexed component
522 * @exception NullPointerException If the specified object argument
524 * @exception IllegalArgumentException If the specified object argument
525 * is not an array, or if the specified value cannot be converted
526 * to the underlying array's component type by an identity or a
527 * primitive widening conversion
528 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
529 * argument is negative, or if it is greater than or equal to
530 * the length of the specified array
533 public static void setInt(Object array, int index, int i)
534 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
535 Class<?> t = array.getClass().getComponentType();
536 if (t == Integer.TYPE) {
537 int[] arr = (int[]) array;
540 setLong(array, index, i);
545 * Sets the value of the indexed component of the specified array
546 * object to the specified {@code long} value.
547 * @param array the array
548 * @param index the index into the array
549 * @param l the new value of the indexed component
550 * @exception NullPointerException If the specified object argument
552 * @exception IllegalArgumentException If the specified object argument
553 * is not an array, or if the specified value cannot be converted
554 * to the underlying array's component type by an identity or a
555 * primitive widening conversion
556 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
557 * argument is negative, or if it is greater than or equal to
558 * the length of the specified array
561 public static void setLong(Object array, int index, long l)
562 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
563 Class<?> t = array.getClass().getComponentType();
564 if (t == Long.TYPE) {
565 long[] arr = (long[]) array;
568 setFloat(array, index, l);
573 * Sets the value of the indexed component of the specified array
574 * object to the specified {@code float} value.
575 * @param array the array
576 * @param index the index into the array
577 * @param f the new value of the indexed component
578 * @exception NullPointerException If the specified object argument
580 * @exception IllegalArgumentException If the specified object argument
581 * is not an array, or if the specified value cannot be converted
582 * to the underlying array's component type by an identity or a
583 * primitive widening conversion
584 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
585 * argument is negative, or if it is greater than or equal to
586 * the length of the specified array
589 public static void setFloat(Object array, int index, float f)
590 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
591 Class<?> t = array.getClass().getComponentType();
592 if (t == Float.TYPE) {
593 float[] arr = (float[])array;
596 setDouble(array, index, f);
601 * Sets the value of the indexed component of the specified array
602 * object to the specified {@code double} value.
603 * @param array the array
604 * @param index the index into the array
605 * @param d the new value of the indexed component
606 * @exception NullPointerException If the specified object argument
608 * @exception IllegalArgumentException If the specified object argument
609 * is not an array, or if the specified value cannot be converted
610 * to the underlying array's component type by an identity or a
611 * primitive widening conversion
612 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
613 * argument is negative, or if it is greater than or equal to
614 * the length of the specified array
617 public static void setDouble(Object array, int index, double d)
618 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
619 Class<?> t = array.getClass().getComponentType();
620 if (t == Double.TYPE) {
621 double[] arr = (double[])array;
624 throw new IllegalArgumentException("argument type mismatch");
632 @JavaScriptBody(args = { "primitive", "sig", "length" }, body =
633 "var arr = new Array(length);\n"
634 + "var value = primitive ? 0 : null;\n"
635 + "for(var i = 0; i < length; i++) arr[i] = value;\n"
636 + "arr.jvmName = sig;\n"
639 private static native Object newArray(boolean primitive, String sig, int length);
641 private static Object multiNewArray(String sig, int[] dims, int index)
642 throws IllegalArgumentException, NegativeArraySizeException {
643 if (dims.length == index + 1) {
644 return newArray(sig.length() == 2, sig, dims[index]);
646 Object arr = newArray(false, sig, dims[index]);
647 String compsig = sig.substring(1);
648 int len = getLength(arr);
649 for (int i = 0; i < len; i++) {
650 setArray(arr, i, multiNewArray(compsig, dims, index + 1));
654 private static Object fromPrimitive(Class<?> t, Object array, int index) {
655 return Method.fromPrimitive(t, atArray(array, index));
658 @JavaScriptBody(args = { "array", "index" }, body = "return array[index];")
659 private static native Object atArray(Object array, int index);
661 @JavaScriptBody(args = { "array", "index", "v" }, body = "array[index] = v;")
662 private static native Object setArray(Object array, int index, Object v);