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.Exported;
29 import org.apidesign.bck2brwsr.core.JavaScriptBody;
30 import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
33 * The {@code Array} class provides static methods to dynamically create and
36 * <p>{@code Array} permits widening conversions to occur during a get or set
37 * operation, but throws an {@code IllegalArgumentException} if a narrowing
38 * conversion would occur.
40 * @author Nakul Saraiya
42 @JavaScriptPrototype(prototype = "new Array", container = "Array.prototype")
47 * Constructor. Class Array is not instantiable.
52 * Creates a new array with the specified component type and
54 * Invoking this method is equivalent to creating an array
59 * Array.newInstance(componentType, x);
63 * @param componentType the {@code Class} object representing the
64 * component type of the new array
65 * @param length the length of the new array
66 * @return the new array
67 * @exception NullPointerException if the specified
68 * {@code componentType} parameter is null
69 * @exception IllegalArgumentException if componentType is {@link Void#TYPE}
70 * @exception NegativeArraySizeException if the specified {@code length}
73 public static Object newInstance(Class<?> componentType, int length)
74 throws NegativeArraySizeException {
76 throw new NegativeArraySizeException();
78 String sig = findSignature(componentType);
79 return newArray(componentType.isPrimitive(), sig, length);
82 private static String findSignature(Class<?> type) {
83 if (type == Integer.TYPE) {
86 if (type == Long.TYPE) {
89 if (type == Double.TYPE) {
92 if (type == Float.TYPE) {
95 if (type == Byte.TYPE) {
98 if (type == Boolean.TYPE) {
101 if (type == Short.TYPE) {
104 if (type == Character.TYPE) {
107 if (type.getName().equals("void")) {
108 throw new IllegalStateException("Can't create array for " + type);
110 return "[L" + type.getName() + ";";
113 * Creates a new array
114 * with the specified component type and dimensions.
115 * If {@code componentType}
116 * represents a non-array class or interface, the new array
117 * has {@code dimensions.length} dimensions and
118 * {@code componentType} as its component type. If
119 * {@code componentType} represents an array class, the
120 * number of dimensions of the new array is equal to the sum
121 * of {@code dimensions.length} and the number of
122 * dimensions of {@code componentType}. In this case, the
123 * component type of the new array is the component type of
124 * {@code componentType}.
126 * <p>The number of dimensions of the new array must not
127 * exceed the number of array dimensions supported by the
128 * implementation (typically 255).
130 * @param componentType the {@code Class} object representing the component
131 * type of the new array
132 * @param dimensions an array of {@code int} representing the dimensions of
134 * @return the new array
135 * @exception NullPointerException if the specified
136 * {@code componentType} argument is null
137 * @exception IllegalArgumentException if the specified {@code dimensions}
138 * argument is a zero-dimensional array, or if the number of
139 * requested dimensions exceeds the limit on the number of array dimensions
140 * supported by the implementation (typically 255), or if componentType
141 * is {@link Void#TYPE}.
142 * @exception NegativeArraySizeException if any of the components in
143 * the specified {@code dimensions} argument is negative.
145 public static Object newInstance(Class<?> componentType, int... dimensions)
146 throws IllegalArgumentException, NegativeArraySizeException {
147 StringBuilder sig = new StringBuilder();
148 for (int i = 1; i < dimensions.length; i++) {
151 sig.append(findSignature(componentType));
152 return multiNewArray(sig.toString(), dimensions, 0);
156 * Returns the length of the specified array object, as an {@code int}.
158 * @param array the array
159 * @return the length of the array
160 * @exception IllegalArgumentException if the object argument is not
163 public static int getLength(Object array)
164 throws IllegalArgumentException {
165 if (!array.getClass().isArray()) {
166 throw new IllegalArgumentException("Argument is not an array");
168 return length(array);
171 @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
172 private static native int length(Object arr);
175 * Returns the value of the indexed component in the specified
176 * array object. The value is automatically wrapped in an object
177 * if it has a primitive type.
179 * @param array the array
180 * @param index the index
181 * @return the (possibly wrapped) value of the indexed component in
182 * the specified array
183 * @exception NullPointerException If the specified object is null
184 * @exception IllegalArgumentException If the specified object is not
186 * @exception 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
190 public static Object get(Object array, int index)
191 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
192 final Class<?> t = array.getClass().getComponentType();
193 if (t.isPrimitive()) {
194 return fromPrimitive(t, array, index);
196 return ((Object[])array)[index];
201 * Returns the value of the indexed component in the specified
202 * array object, as a {@code boolean}.
204 * @param array the array
205 * @param index the index
206 * @return the value of the indexed component in the specified array
207 * @exception NullPointerException If the specified object is null
208 * @exception IllegalArgumentException If the specified object is not
209 * an array, or if the indexed element cannot be converted to the
210 * return type by an identity or widening conversion
211 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
212 * argument is negative, or if it is greater than or equal to the
213 * length of the specified array
216 public static native boolean getBoolean(Object array, int index)
217 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
220 * Returns the value of the indexed component in the specified
221 * array object, as a {@code byte}.
223 * @param array the array
224 * @param index the index
225 * @return the value of the indexed component in the specified array
226 * @exception NullPointerException If the specified object is null
227 * @exception IllegalArgumentException If the specified object is not
228 * an array, or if the indexed element cannot be converted to the
229 * return type by an identity or widening conversion
230 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
231 * argument is negative, or if it is greater than or equal to the
232 * length of the specified array
235 public static byte getByte(Object array, int index)
236 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
237 if (array.getClass().getComponentType() != Byte.TYPE) {
238 throw new IllegalArgumentException();
240 byte[] arr = (byte[]) array;
245 * Returns the value of the indexed component in the specified
246 * array object, as a {@code char}.
248 * @param array the array
249 * @param index the index
250 * @return the value of the indexed component in the specified array
251 * @exception NullPointerException If the specified object is null
252 * @exception IllegalArgumentException If the specified object is not
253 * an array, or if the indexed element cannot be converted to the
254 * return type by an identity or widening conversion
255 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
256 * argument is negative, or if it is greater than or equal to the
257 * length of the specified array
260 public static native char getChar(Object array, int index)
261 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
264 * Returns the value of the indexed component in the specified
265 * array object, as a {@code short}.
267 * @param array the array
268 * @param index the index
269 * @return the value of the indexed component in the specified array
270 * @exception NullPointerException If the specified object is null
271 * @exception IllegalArgumentException If the specified object is not
272 * an array, or if the indexed element cannot be converted to the
273 * return type by an identity or widening conversion
274 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
275 * argument is negative, or if it is greater than or equal to the
276 * length of the specified array
279 public static short getShort(Object array, int index)
280 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
281 final Class<?> t = array.getClass().getComponentType();
282 if (t == Short.TYPE) {
283 short[] arr = (short[]) array;
286 return getByte(array, index);
290 * Returns the value of the indexed component in the specified
291 * array object, as an {@code int}.
293 * @param array the array
294 * @param index the index
295 * @return the value of the indexed component in the specified array
296 * @exception NullPointerException If the specified object is null
297 * @exception 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 * @exception 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
305 public static int getInt(Object array, int index)
306 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
307 final Class<?> t = array.getClass().getComponentType();
308 if (t == Integer.TYPE) {
309 int[] arr = (int[]) array;
312 return getShort(array, index);
316 * Returns the value of the indexed component in the specified
317 * array object, as a {@code long}.
319 * @param array the array
320 * @param index the index
321 * @return the value of the indexed component in the specified array
322 * @exception NullPointerException If the specified object is null
323 * @exception IllegalArgumentException If the specified object is not
324 * an array, or if the indexed element cannot be converted to the
325 * return type by an identity or widening conversion
326 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
327 * argument is negative, or if it is greater than or equal to the
328 * length of the specified array
331 public static long getLong(Object array, int index)
332 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
333 final Class<?> t = array.getClass().getComponentType();
334 if (t == Long.TYPE) {
335 long[] arr = (long[]) array;
338 return getInt(array, index);
342 * Returns the value of the indexed component in the specified
343 * array object, as a {@code float}.
345 * @param array the array
346 * @param index the index
347 * @return the value of the indexed component in the specified array
348 * @exception NullPointerException If the specified object is null
349 * @exception IllegalArgumentException If the specified object is not
350 * an array, or if the indexed element cannot be converted to the
351 * return type by an identity or widening conversion
352 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
353 * argument is negative, or if it is greater than or equal to the
354 * length of the specified array
357 public static float getFloat(Object array, int index)
358 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
359 final Class<?> t = array.getClass().getComponentType();
360 if (t == Float.TYPE) {
361 float[] arr = (float[]) array;
364 return getLong(array, index);
368 * Returns the value of the indexed component in the specified
369 * array object, as a {@code double}.
371 * @param array the array
372 * @param index the index
373 * @return the value of the indexed component in the specified array
374 * @exception NullPointerException If the specified object is null
375 * @exception IllegalArgumentException If the specified object is not
376 * an array, or if the indexed element cannot be converted to the
377 * return type by an identity or widening conversion
378 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
379 * argument is negative, or if it is greater than or equal to the
380 * length of the specified array
383 public static double getDouble(Object array, int index)
384 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
385 final Class<?> t = array.getClass().getComponentType();
386 if (t == Double.TYPE) {
387 double[] arr = (double[]) array;
390 return getFloat(array, index);
394 * Sets the value of the indexed component of the specified array
395 * object to the specified new value. The new value is first
396 * automatically unwrapped if the array has a primitive component
398 * @param array the array
399 * @param index the index into the array
400 * @param value the new value of the indexed component
401 * @exception NullPointerException If the specified object argument
403 * @exception IllegalArgumentException If the specified object argument
404 * is not an array, or if the array component type is primitive and
405 * an unwrapping conversion fails
406 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
407 * argument is negative, or if it is greater than or equal to
408 * the length of the specified array
410 public static void set(Object array, int index, Object value)
411 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
412 if (array.getClass().getComponentType().isPrimitive()) {
413 throw new IllegalArgumentException();
415 Object[] arr = (Object[])array;
421 * Sets the value of the indexed component of the specified array
422 * object to the specified {@code boolean} value.
423 * @param array the array
424 * @param index the index into the array
425 * @param z the new value of the indexed component
426 * @exception NullPointerException If the specified object argument
428 * @exception IllegalArgumentException If the specified object argument
429 * is not an array, or if the specified value cannot be converted
430 * to the underlying array's component type by an identity or a
431 * primitive widening conversion
432 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
433 * argument is negative, or if it is greater than or equal to
434 * the length of the specified array
437 public static native void setBoolean(Object array, int index, boolean z)
438 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
441 * Sets the value of the indexed component of the specified array
442 * object to the specified {@code byte} value.
443 * @param array the array
444 * @param index the index into the array
445 * @param b the new value of the indexed component
446 * @exception NullPointerException If the specified object argument
448 * @exception IllegalArgumentException If the specified object argument
449 * is not an array, or if the specified value cannot be converted
450 * to the underlying array's component type by an identity or a
451 * primitive widening conversion
452 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
453 * argument is negative, or if it is greater than or equal to
454 * the length of the specified array
457 public static void setByte(Object array, int index, byte b)
458 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
459 Class<?> t = array.getClass().getComponentType();
460 if (t == Byte.TYPE) {
461 byte[] arr = (byte[]) array;
464 setShort(array, index, b);
469 * Sets the value of the indexed component of the specified array
470 * object to the specified {@code char} value.
471 * @param array the array
472 * @param index the index into the array
473 * @param c the new value of the indexed component
474 * @exception NullPointerException If the specified object argument
476 * @exception IllegalArgumentException If the specified object argument
477 * is not an array, or if the specified value cannot be converted
478 * to the underlying array's component type by an identity or a
479 * primitive widening conversion
480 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
481 * argument is negative, or if it is greater than or equal to
482 * the length of the specified array
485 public static native void setChar(Object array, int index, char c)
486 throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
489 * Sets the value of the indexed component of the specified array
490 * object to the specified {@code short} value.
491 * @param array the array
492 * @param index the index into the array
493 * @param s the new value of the indexed component
494 * @exception NullPointerException If the specified object argument
496 * @exception IllegalArgumentException If the specified object argument
497 * is not an array, or if the specified value cannot be converted
498 * to the underlying array's component type by an identity or a
499 * primitive widening conversion
500 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
501 * argument is negative, or if it is greater than or equal to
502 * the length of the specified array
505 public static void setShort(Object array, int index, short s)
506 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
507 Class<?> t = array.getClass().getComponentType();
508 if (t == Short.TYPE) {
509 short[] arr = (short[]) array;
512 setInt(array, index, s);
518 * Sets the value of the indexed component of the specified array
519 * object to the specified {@code int} value.
520 * @param array the array
521 * @param index the index into the array
522 * @param i the new value of the indexed component
523 * @exception NullPointerException If the specified object argument
525 * @exception IllegalArgumentException If the specified object argument
526 * is not an array, or if the specified value cannot be converted
527 * to the underlying array's component type by an identity or a
528 * primitive widening conversion
529 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
530 * argument is negative, or if it is greater than or equal to
531 * the length of the specified array
534 public static void setInt(Object array, int index, int i)
535 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
536 Class<?> t = array.getClass().getComponentType();
537 if (t == Integer.TYPE) {
538 int[] arr = (int[]) array;
541 setLong(array, index, i);
546 * Sets the value of the indexed component of the specified array
547 * object to the specified {@code long} value.
548 * @param array the array
549 * @param index the index into the array
550 * @param l the new value of the indexed component
551 * @exception NullPointerException If the specified object argument
553 * @exception IllegalArgumentException If the specified object argument
554 * is not an array, or if the specified value cannot be converted
555 * to the underlying array's component type by an identity or a
556 * primitive widening conversion
557 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
558 * argument is negative, or if it is greater than or equal to
559 * the length of the specified array
562 public static void setLong(Object array, int index, long l)
563 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
564 Class<?> t = array.getClass().getComponentType();
565 if (t == Long.TYPE) {
566 long[] arr = (long[]) array;
569 setFloat(array, index, l);
574 * Sets the value of the indexed component of the specified array
575 * object to the specified {@code float} value.
576 * @param array the array
577 * @param index the index into the array
578 * @param f the new value of the indexed component
579 * @exception NullPointerException If the specified object argument
581 * @exception IllegalArgumentException If the specified object argument
582 * is not an array, or if the specified value cannot be converted
583 * to the underlying array's component type by an identity or a
584 * primitive widening conversion
585 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
586 * argument is negative, or if it is greater than or equal to
587 * the length of the specified array
590 public static void setFloat(Object array, int index, float f)
591 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
592 Class<?> t = array.getClass().getComponentType();
593 if (t == Float.TYPE) {
594 float[] arr = (float[])array;
597 setDouble(array, index, f);
602 * Sets the value of the indexed component of the specified array
603 * object to the specified {@code double} value.
604 * @param array the array
605 * @param index the index into the array
606 * @param d the new value of the indexed component
607 * @exception NullPointerException If the specified object argument
609 * @exception IllegalArgumentException If the specified object argument
610 * is not an array, or if the specified value cannot be converted
611 * to the underlying array's component type by an identity or a
612 * primitive widening conversion
613 * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
614 * argument is negative, or if it is greater than or equal to
615 * the length of the specified array
618 public static void setDouble(Object array, int index, double d)
619 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
620 Class<?> t = array.getClass().getComponentType();
621 if (t == Double.TYPE) {
622 double[] arr = (double[])array;
625 throw new IllegalArgumentException("argument type mismatch");
633 @JavaScriptBody(args = { "primitive", "sig", "length" }, body =
634 "var arr = new Array(length);\n"
635 + "var value = primitive ? 0 : null;\n"
636 + "for(var i = 0; i < length; i++) arr[i] = value;\n"
637 + "arr.jvmName = sig;\n"
641 private static native Object newArray(boolean primitive, String sig, int length);
645 private static Object multiNewArray(String sig, int[] dims, int index)
646 throws IllegalArgumentException, NegativeArraySizeException {
647 if (dims.length == index + 1) {
648 return newArray(sig.length() == 2, sig, dims[index]);
650 Object arr = newArray(false, sig, dims[index]);
651 String compsig = sig.substring(1);
652 int len = getLength(arr);
653 for (int i = 0; i < len; i++) {
654 setArray(arr, i, multiNewArray(compsig, dims, index + 1));
658 private static Object fromPrimitive(Class<?> t, Object array, int index) {
659 return Method.fromPrimitive(t, atArray(array, index));
662 @JavaScriptBody(args = { "array", "index" }, body = "return array[index];")
663 private static native Object atArray(Object array, int index);
665 @JavaScriptBody(args = { "array", "index", "v" }, body = "array[index] = v;")
666 private static native Object setArray(Object array, int index, Object v);