1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.lang.reflect;
28 
29 import dalvik.annotation.optimization.FastNative;
30 
31 /**
32  * The {@code Array} class provides static methods to dynamically create and
33  * access Java arrays.
34  *
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.
38  *
39  * @author Nakul Saraiya
40  * @since 1.1
41  */
42 public final
43 class Array {
44 
45     /**
46      * Constructor.  Class Array is not instantiable.
47      */
Array()48     private Array() {}
49 
50     /**
51      * Creates a new array with the specified component type and
52      * length.
53      * Invoking this method is equivalent to creating an array
54      * as follows:
55      * <blockquote>
56      * <pre>
57      * int[] x = {length};
58      * Array.newInstance(componentType, x);
59      * </pre>
60      * </blockquote>
61      *
62      * <p>The number of dimensions of the new array must not
63      * exceed 255.
64      *
65      * @param componentType the {@code Class} object representing the
66      * component type of the new array
67      * @param length the length of the new array
68      * @return the new array
69      * @exception NullPointerException if the specified
70      * {@code componentType} parameter is null
71      * @exception IllegalArgumentException if componentType is {@link
72      * Void#TYPE} or if the number of dimensions of the requested array
73      * instance exceed 255.
74      * @exception NegativeArraySizeException if the specified {@code length}
75      * is negative
76      */
newInstance(Class<?> componentType, int length)77     public static Object newInstance(Class<?> componentType, int length)
78         throws NegativeArraySizeException {
79         return newArray(componentType, length);
80     }
81 
82     /**
83      * Creates a new array
84      * with the specified component type and dimensions.
85      * If {@code componentType}
86      * represents a non-array class or interface, the new array
87      * has {@code dimensions.length} dimensions and
88      * {@code componentType} as its component type. If
89      * {@code componentType} represents an array class, the
90      * number of dimensions of the new array is equal to the sum
91      * of {@code dimensions.length} and the number of
92      * dimensions of {@code componentType}. In this case, the
93      * component type of the new array is the component type of
94      * {@code componentType}.
95      *
96      * <p>The number of dimensions of the new array must not
97      * exceed 255.
98      *
99      * @param componentType the {@code Class} object representing the component
100      * type of the new array
101      * @param dimensions an array of {@code int} representing the dimensions of
102      * the new array
103      * @return the new array
104      * @exception NullPointerException if the specified
105      * {@code componentType} argument is null
106      * @exception IllegalArgumentException if the specified {@code dimensions}
107      * argument is a zero-dimensional array, if componentType is {@link
108      * Void#TYPE}, or if the number of dimensions of the requested array
109      * instance exceed 255.
110      * @exception NegativeArraySizeException if any of the components in
111      * the specified {@code dimensions} argument is negative.
112      */
newInstance(Class<?> componentType, int... dimensions)113     public static Object newInstance(Class<?> componentType, int... dimensions)
114         throws IllegalArgumentException, NegativeArraySizeException {
115         // Android-changed: New implementation of newInstance(Class, int...).
116         if (dimensions.length <= 0 || dimensions.length > 255) {
117             throw new IllegalArgumentException("Bad number of dimensions: " + dimensions.length);
118         }
119         if (componentType == void.class) {
120             throw new IllegalArgumentException("Can't allocate an array of void");
121         }
122         if (componentType == null) {
123             throw new NullPointerException("componentType == null");
124         }
125         return createMultiArray(componentType, dimensions);
126     }
127 
128     /**
129      * Returns the length of the specified array object, as an {@code int}.
130      *
131      * @param array the array
132      * @return the length of the array
133      * @exception IllegalArgumentException if the object argument is not
134      * an array
135      */
136     // Android-changed: Non-native implementation of getLength(Object).
137     // Android-changed: Removal of explicit throws IllegalArgumentException from method signature.
getLength(Object array)138     public static int getLength(Object array)
139         /* throws IllegalArgumentException */ {
140         if (array instanceof Object[]) {
141             return ((Object[]) array).length;
142         } else if (array instanceof boolean[]) {
143             return ((boolean[]) array).length;
144         } else if (array instanceof byte[]) {
145             return ((byte[]) array).length;
146         } else if (array instanceof char[]) {
147             return ((char[]) array).length;
148         } else if (array instanceof double[]) {
149             return ((double[]) array).length;
150         } else if (array instanceof float[]) {
151             return ((float[]) array).length;
152         } else if (array instanceof int[]) {
153             return ((int[]) array).length;
154         } else if (array instanceof long[]) {
155             return ((long[]) array).length;
156         } else if (array instanceof short[]) {
157             return ((short[]) array).length;
158         }
159         throw badArray(array);
160       }
161 
162     /**
163      * Returns the value of the indexed component in the specified
164      * array object.  The value is automatically wrapped in an object
165      * if it has a primitive type.
166      *
167      * @param array the array
168      * @param index the index
169      * @return the (possibly wrapped) value of the indexed component in
170      * the specified array
171      * @exception NullPointerException If the specified object is null
172      * @exception IllegalArgumentException If the specified object is not
173      * an array
174      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
175      * argument is negative, or if it is greater than or equal to the
176      * length of the specified array
177      */
178     // Android-changed: Non-native implementation of get(Object, int).
get(Object array, int index)179     public static Object get(Object array, int index)
180         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
181         if (array instanceof Object[]) {
182             return ((Object[]) array)[index];
183         }
184         if (array instanceof boolean[]) {
185             return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE;
186         }
187         if (array instanceof byte[]) {
188             return Byte.valueOf(((byte[]) array)[index]);
189         }
190         if (array instanceof char[]) {
191             return Character.valueOf(((char[]) array)[index]);
192         }
193         if (array instanceof short[]) {
194             return Short.valueOf(((short[]) array)[index]);
195         }
196         if (array instanceof int[]) {
197             return Integer.valueOf(((int[]) array)[index]);
198         }
199         if (array instanceof long[]) {
200             return Long.valueOf(((long[]) array)[index]);
201         }
202         if (array instanceof float[]) {
203             return new Float(((float[]) array)[index]);
204         }
205         if (array instanceof double[]) {
206             return new Double(((double[]) array)[index]);
207         }
208         if (array == null) {
209             throw new NullPointerException("array == null");
210         }
211         throw notAnArray(array);
212     }
213 
214     /**
215      * Returns the value of the indexed component in the specified
216      * array object, as a {@code boolean}.
217      *
218      * @param array the array
219      * @param index the index
220      * @return the value of the indexed component in the specified array
221      * @exception NullPointerException If the specified object is null
222      * @exception IllegalArgumentException If the specified object is not
223      * an array, or if the indexed element cannot be converted to the
224      * return type by an identity or widening conversion
225      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
226      * argument is negative, or if it is greater than or equal to the
227      * length of the specified array
228      * @see Array#get
229      */
230     // Android-changed: Non-native implementation of getBoolean(Object, int).
getBoolean(Object array, int index)231     public static boolean getBoolean(Object array, int index)
232         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
233         if (array instanceof boolean[]) {
234             return ((boolean[]) array)[index];
235         }
236         throw badArray(array);
237     }
238 
239     /**
240      * Returns the value of the indexed component in the specified
241      * array object, as a {@code byte}.
242      *
243      * @param array the array
244      * @param index the index
245      * @return the value of the indexed component in the specified array
246      * @exception NullPointerException If the specified object is null
247      * @exception IllegalArgumentException If the specified object is not
248      * an array, or if the indexed element cannot be converted to the
249      * return type by an identity or widening conversion
250      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
251      * argument is negative, or if it is greater than or equal to the
252      * length of the specified array
253      * @see Array#get
254      */
255     // Android-changed: Non-native implementation of getByte(Object, int).
getByte(Object array, int index)256     public static byte getByte(Object array, int index)
257         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
258         if (array instanceof byte[]) {
259             return ((byte[]) array)[index];
260         }
261         throw badArray(array);
262     }
263 
264     /**
265      * Returns the value of the indexed component in the specified
266      * array object, as a {@code char}.
267      *
268      * @param array the array
269      * @param index the index
270      * @return the value of the indexed component in the specified array
271      * @exception NullPointerException If the specified object is null
272      * @exception IllegalArgumentException If the specified object is not
273      * an array, or if the indexed element cannot be converted to the
274      * return type by an identity or widening conversion
275      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
276      * argument is negative, or if it is greater than or equal to the
277      * length of the specified array
278      * @see Array#get
279      */
280     // Android-changed: Non-native implementation of getChar(Object, int).
getChar(Object array, int index)281     public static char getChar(Object array, int index)
282         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
283         if (array instanceof char[]) {
284             return ((char[]) array)[index];
285         }
286         throw badArray(array);
287     }
288 
289     /**
290      * Returns the value of the indexed component in the specified
291      * array object, as a {@code short}.
292      *
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
303      * @see Array#get
304      */
305     // Android-changed: Non-native implementation of getShort(Object, int).
getShort(Object array, int index)306     public static short getShort(Object array, int index)
307         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
308         if (array instanceof short[]) {
309             return ((short[]) array)[index];
310         } else if (array instanceof byte[]) {
311             return ((byte[]) array)[index];
312         }
313         throw badArray(array);
314     }
315 
316     /**
317      * Returns the value of the indexed component in the specified
318      * array object, as an {@code int}.
319      *
320      * @param array the array
321      * @param index the index
322      * @return the value of the indexed component in the specified array
323      * @exception NullPointerException If the specified object is null
324      * @exception IllegalArgumentException If the specified object is not
325      * an array, or if the indexed element cannot be converted to the
326      * return type by an identity or widening conversion
327      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
328      * argument is negative, or if it is greater than or equal to the
329      * length of the specified array
330      * @see Array#get
331      */
332     // Android-changed: Non-native implementation of getInt(Object, int).
getInt(Object array, int index)333     public static int getInt(Object array, int index)
334         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
335         if (array instanceof int[]) {
336             return ((int[]) array)[index];
337         } else if (array instanceof byte[]) {
338             return ((byte[]) array)[index];
339         } else if (array instanceof char[]) {
340             return ((char[]) array)[index];
341         } else if (array instanceof short[]) {
342             return ((short[]) array)[index];
343         }
344         throw badArray(array);
345     }
346 
347     /**
348      * Returns the value of the indexed component in the specified
349      * array object, as a {@code long}.
350      *
351      * @param array the array
352      * @param index the index
353      * @return the value of the indexed component in the specified array
354      * @exception NullPointerException If the specified object is null
355      * @exception IllegalArgumentException If the specified object is not
356      * an array, or if the indexed element cannot be converted to the
357      * return type by an identity or widening conversion
358      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
359      * argument is negative, or if it is greater than or equal to the
360      * length of the specified array
361      * @see Array#get
362      */
363     // Android-changed: Non-native implementation of getLong(Object, int).
getLong(Object array, int index)364     public static long getLong(Object array, int index)
365         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
366         if (array instanceof long[]) {
367             return ((long[]) array)[index];
368         } else if (array instanceof byte[]) {
369             return ((byte[]) array)[index];
370         } else if (array instanceof char[]) {
371             return ((char[]) array)[index];
372         } else if (array instanceof int[]) {
373             return ((int[]) array)[index];
374         } else if (array instanceof short[]) {
375             return ((short[]) array)[index];
376         }
377         throw badArray(array);
378     }
379 
380     /**
381      * Returns the value of the indexed component in the specified
382      * array object, as a {@code float}.
383      *
384      * @param array the array
385      * @param index the index
386      * @return the value of the indexed component in the specified array
387      * @exception NullPointerException If the specified object is null
388      * @exception IllegalArgumentException If the specified object is not
389      * an array, or if the indexed element cannot be converted to the
390      * return type by an identity or widening conversion
391      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
392      * argument is negative, or if it is greater than or equal to the
393      * length of the specified array
394      * @see Array#get
395      */
396     // Android-changed: Non-native implementation of getFloat(Object, int).
getFloat(Object array, int index)397     public static float getFloat(Object array, int index)
398         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
399         if (array instanceof float[]) {
400             return ((float[]) array)[index];
401         } else if (array instanceof byte[]) {
402             return ((byte[]) array)[index];
403         } else if (array instanceof char[]) {
404             return ((char[]) array)[index];
405         } else if (array instanceof int[]) {
406             return ((int[]) array)[index];
407         } else if (array instanceof long[]) {
408             return ((long[]) array)[index];
409         } else if (array instanceof short[]) {
410             return ((short[]) array)[index];
411         }
412         throw badArray(array);
413     }
414 
415     /**
416      * Returns the value of the indexed component in the specified
417      * array object, as a {@code double}.
418      *
419      * @param array the array
420      * @param index the index
421      * @return the value of the indexed component in the specified array
422      * @exception NullPointerException If the specified object is null
423      * @exception IllegalArgumentException If the specified object is not
424      * an array, or if the indexed element cannot be converted to the
425      * return type by an identity or widening conversion
426      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
427      * argument is negative, or if it is greater than or equal to the
428      * length of the specified array
429      * @see Array#get
430      */
431     // Android-changed: Non-native implementation of getDouble(Object, int).
getDouble(Object array, int index)432     public static double getDouble(Object array, int index)
433         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
434         if (array instanceof double[]) {
435             return ((double[]) array)[index];
436         } else if (array instanceof byte[]) {
437             return ((byte[]) array)[index];
438         } else if (array instanceof char[]) {
439             return ((char[]) array)[index];
440         } else if (array instanceof float[]) {
441             return ((float[]) array)[index];
442         } else if (array instanceof int[]) {
443             return ((int[]) array)[index];
444         } else if (array instanceof long[]) {
445             return ((long[]) array)[index];
446         } else if (array instanceof short[]) {
447             return ((short[]) array)[index];
448         }
449         throw badArray(array);
450     }
451 
452     /**
453      * Sets the value of the indexed component of the specified array
454      * object to the specified new value.  The new value is first
455      * automatically unwrapped if the array has a primitive component
456      * type.
457      * @param array the array
458      * @param index the index into the array
459      * @param value the new value of the indexed component
460      * @exception NullPointerException If the specified object argument
461      * is null
462      * @exception IllegalArgumentException If the specified object argument
463      * is not an array, or if the array component type is primitive and
464      * an unwrapping conversion fails
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
468      */
469     // Android-changed: Non-native implementation of set(Object, int, Object).
set(Object array, int index, Object value)470     public static void set(Object array, int index, Object value)
471         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
472         if (!array.getClass().isArray()) {
473             throw notAnArray(array);
474         }
475 
476         if (array instanceof Object[]) {
477             if (value != null && !array.getClass().getComponentType().isInstance(value)) {
478                 throw incompatibleType(array);
479             }
480             ((Object[]) array)[index] = value;
481         } else {
482             if (value == null) {
483                 throw new IllegalArgumentException("Primitive array can't take null values.");
484             }
485             if (value instanceof Boolean) {
486                 setBoolean(array, index, ((Boolean) value).booleanValue());
487             } else if (value instanceof Byte) {
488                 setByte(array, index, ((Byte) value).byteValue());
489             } else if (value instanceof Character) {
490                 setChar(array, index, ((Character) value).charValue());
491             } else if (value instanceof Short) {
492                 setShort(array, index, ((Short) value).shortValue());
493             } else if (value instanceof Integer) {
494                 setInt(array, index, ((Integer) value).intValue());
495             } else if (value instanceof Long) {
496                 setLong(array, index, ((Long) value).longValue());
497             } else if (value instanceof Float) {
498                 setFloat(array, index, ((Float) value).floatValue());
499             } else if (value instanceof Double) {
500                 setDouble(array, index, ((Double) value).doubleValue());
501             }
502         }
503     }
504 
505     /**
506      * Sets the value of the indexed component of the specified array
507      * object to the specified {@code boolean} value.
508      * @param array the array
509      * @param index the index into the array
510      * @param z the new value of the indexed component
511      * @exception NullPointerException If the specified object argument
512      * is null
513      * @exception IllegalArgumentException If the specified object argument
514      * is not an array, or if the specified value cannot be converted
515      * to the underlying array's component type by an identity or a
516      * primitive widening conversion
517      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
518      * argument is negative, or if it is greater than or equal to
519      * the length of the specified array
520      * @see Array#set
521      */
522     // Android-changed: Non-native implementation of setBoolean(Object, int, boolean).
523     // Android-changed: Removal of explicit runtime exceptions throws clause.
setBoolean(Object array, int index, boolean z)524     public static void setBoolean(Object array, int index, boolean z)
525         /* throws IllegalArgumentException, ArrayIndexOutOfBoundsException */ {
526         if (array instanceof boolean[]) {
527             ((boolean[]) array)[index] = z;
528         } else {
529             throw badArray(array);
530         }
531     }
532 
533     /**
534      * Sets the value of the indexed component of the specified array
535      * object to the specified {@code byte} value.
536      * @param array the array
537      * @param index the index into the array
538      * @param b the new value of the indexed component
539      * @exception NullPointerException If the specified object argument
540      * is null
541      * @exception IllegalArgumentException If the specified object argument
542      * is not an array, or if the specified value cannot be converted
543      * to the underlying array's component type by an identity or a
544      * primitive widening conversion
545      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
546      * argument is negative, or if it is greater than or equal to
547      * the length of the specified array
548      * @see Array#set
549      */
550     // Android-changed: Non-native implementation of setByte(Object, int, byte).
setByte(Object array, int index, byte b)551     public static void setByte(Object array, int index, byte b)
552         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
553         if (array instanceof byte[]) {
554             ((byte[]) array)[index] = b;
555         } else if (array instanceof double[]) {
556             ((double[]) array)[index] = b;
557         } else if (array instanceof float[]) {
558             ((float[]) array)[index] = b;
559         } else if (array instanceof int[]) {
560             ((int[]) array)[index] = b;
561         } else if (array instanceof long[]) {
562             ((long[]) array)[index] = b;
563         } else if (array instanceof short[]) {
564             ((short[]) array)[index] = b;
565         } else {
566             throw badArray(array);
567         }
568     }
569 
570     /**
571      * Sets the value of the indexed component of the specified array
572      * object to the specified {@code char} value.
573      * @param array the array
574      * @param index the index into the array
575      * @param c the new value of the indexed component
576      * @exception NullPointerException If the specified object argument
577      * is null
578      * @exception IllegalArgumentException If the specified object argument
579      * is not an array, or if the specified value cannot be converted
580      * to the underlying array's component type by an identity or a
581      * primitive widening conversion
582      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
583      * argument is negative, or if it is greater than or equal to
584      * the length of the specified array
585      * @see Array#set
586      */
587     // Android-changed: Non-native implementation of setChar(Object, int, char).
setChar(Object array, int index, char c)588     public static void setChar(Object array, int index, char c)
589         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
590         if (array instanceof char[]) {
591             ((char[]) array)[index] = c;
592         } else if (array instanceof double[]) {
593             ((double[]) array)[index] = c;
594         } else if (array instanceof float[]) {
595             ((float[]) array)[index] = c;
596         } else if (array instanceof int[]) {
597             ((int[]) array)[index] = c;
598         } else if (array instanceof long[]) {
599             ((long[]) array)[index] = c;
600         } else {
601             throw badArray(array);
602         }
603     }
604 
605     /**
606      * Sets the value of the indexed component of the specified array
607      * object to the specified {@code short} value.
608      * @param array the array
609      * @param index the index into the array
610      * @param s the new value of the indexed component
611      * @exception NullPointerException If the specified object argument
612      * is null
613      * @exception IllegalArgumentException If the specified object argument
614      * is not an array, or if the specified value cannot be converted
615      * to the underlying array's component type by an identity or a
616      * primitive widening conversion
617      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
618      * argument is negative, or if it is greater than or equal to
619      * the length of the specified array
620      * @see Array#set
621      */
622     // Android-changed: Non-native implementation of setShort(Object, int, short).
setShort(Object array, int index, short s)623     public static void setShort(Object array, int index, short s)
624         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
625         if (array instanceof short[]) {
626             ((short[]) array)[index] = s;
627         } else if (array instanceof double[]) {
628             ((double[]) array)[index] = s;
629         } else if (array instanceof float[]) {
630             ((float[]) array)[index] = s;
631         } else if (array instanceof int[]) {
632             ((int[]) array)[index] = s;
633         } else if (array instanceof long[]) {
634             ((long[]) array)[index] = s;
635         } else {
636             throw badArray(array);
637         }
638     }
639 
640     /**
641      * Sets the value of the indexed component of the specified array
642      * object to the specified {@code int} value.
643      * @param array the array
644      * @param index the index into the array
645      * @param i the new value of the indexed component
646      * @exception NullPointerException If the specified object argument
647      * is null
648      * @exception IllegalArgumentException If the specified object argument
649      * is not an array, or if the specified value cannot be converted
650      * to the underlying array's component type by an identity or a
651      * primitive widening conversion
652      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
653      * argument is negative, or if it is greater than or equal to
654      * the length of the specified array
655      * @see Array#set
656      */
657     // Android-changed: Non-native implementation of setInt(Object, int, int).
setInt(Object array, int index, int i)658     public static void setInt(Object array, int index, int i)
659         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
660         if (array instanceof int[]) {
661             ((int[]) array)[index] = i;
662         } else if (array instanceof double[]) {
663             ((double[]) array)[index] = i;
664         } else if (array instanceof float[]) {
665             ((float[]) array)[index] = i;
666         } else if (array instanceof long[]) {
667             ((long[]) array)[index] = i;
668         } else {
669             throw badArray(array);
670         }
671     }
672 
673     /**
674      * Sets the value of the indexed component of the specified array
675      * object to the specified {@code long} value.
676      * @param array the array
677      * @param index the index into the array
678      * @param l the new value of the indexed component
679      * @exception NullPointerException If the specified object argument
680      * is null
681      * @exception IllegalArgumentException If the specified object argument
682      * is not an array, or if the specified value cannot be converted
683      * to the underlying array's component type by an identity or a
684      * primitive widening conversion
685      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
686      * argument is negative, or if it is greater than or equal to
687      * the length of the specified array
688      * @see Array#set
689      */
690     // Android-changed: Non-native implementation of setBoolean(Object, int, long).
setLong(Object array, int index, long l)691     public static void setLong(Object array, int index, long l)
692         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
693         if (array instanceof long[]) {
694             ((long[]) array)[index] = l;
695         } else if (array instanceof double[]) {
696             ((double[]) array)[index] = l;
697         } else if (array instanceof float[]) {
698             ((float[]) array)[index] = l;
699         } else {
700             throw badArray(array);
701         }
702     }
703 
704     /**
705      * Sets the value of the indexed component of the specified array
706      * object to the specified {@code float} value.
707      * @param array the array
708      * @param index the index into the array
709      * @param f the new value of the indexed component
710      * @exception NullPointerException If the specified object argument
711      * is null
712      * @exception IllegalArgumentException If the specified object argument
713      * is not an array, or if the specified value cannot be converted
714      * to the underlying array's component type by an identity or a
715      * primitive widening conversion
716      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
717      * argument is negative, or if it is greater than or equal to
718      * the length of the specified array
719      * @see Array#set
720      */
setFloat(Object array, int index, float f)721     public static void setFloat(Object array, int index, float f)
722         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
723         if (array instanceof float[]) {
724             ((float[]) array)[index] = f;
725         } else if (array instanceof double[]) {
726             ((double[]) array)[index] = f;
727         } else {
728             throw badArray(array);
729         }
730     }
731 
732     /**
733      * Sets the value of the indexed component of the specified array
734      * object to the specified {@code double} value.
735      * @param array the array
736      * @param index the index into the array
737      * @param d the new value of the indexed component
738      * @exception NullPointerException If the specified object argument
739      * is null
740      * @exception IllegalArgumentException If the specified object argument
741      * is not an array, or if the specified value cannot be converted
742      * to the underlying array's component type by an identity or a
743      * primitive widening conversion
744      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
745      * argument is negative, or if it is greater than or equal to
746      * the length of the specified array
747      * @see Array#set
748      */
749     // Android-changed: Non-native implementation of setDouble(Object, int, double).
setDouble(Object array, int index, double d)750     public static void setDouble(Object array, int index, double d)
751         throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
752         if (array instanceof double[]) {
753             ((double[]) array)[index] = d;
754         } else {
755             throw badArray(array);
756         }
757     }
758 
759     /*
760      * Private
761      */
762 
763     // Android-added: Added javadocs for newArray(Class, int).
764     /**
765      * Returns a new array of the specified component type and length.
766      * Equivalent to {@code new componentType[size]}.
767      *
768      * @throws NullPointerException
769      *             if the component type is null
770      * @throws NegativeArraySizeException
771      *             if {@code size < 0}
772      */
773     // Android-changed: Non-native implementation of newArray(Class, int).
newArray(Class<?> componentType, int length)774     private static Object newArray(Class<?> componentType, int length)
775         throws NegativeArraySizeException {
776         if (!componentType.isPrimitive()) {
777             return createObjectArray(componentType, length);
778         } else if (componentType == char.class) {
779             return new char[length];
780         } else if (componentType == int.class) {
781             return new int[length];
782         } else if (componentType == byte.class) {
783             return new byte[length];
784         } else if (componentType == boolean.class) {
785             return new boolean[length];
786         } else if (componentType == short.class) {
787             return new short[length];
788         } else if (componentType == long.class) {
789             return new long[length];
790         } else if (componentType == float.class) {
791             return new float[length];
792         } else if (componentType == double.class) {
793             return new double[length];
794         } else if (componentType == void.class) {
795             throw new IllegalArgumentException("Can't allocate an array of void");
796         }
797         throw new AssertionError();
798     }
799 
800     // Android-removed: multiNewArray(Class, int[]) method. createMultiArray used instead.
801     /*
802     private static native Object multiNewArray(Class<?> componentType,
803         int[] dimensions)
804         throws IllegalArgumentException, NegativeArraySizeException;
805     */
806 
807     // Android-added: createMultiArray(Class, int[]) method. Used instead of multiNewArray.
808     /*
809      * Create a multi-dimensional array of objects with the specified type.
810      */
811     @FastNative
createMultiArray(Class<?> componentType, int[] dimensions)812     private static native Object createMultiArray(Class<?> componentType, int[] dimensions)
813             throws NegativeArraySizeException;
814 
815     // BEGIN Android-added: Helper methods to support custom method implementations.
816     /*
817      * Create a one-dimensional array of objects with the specified type.
818      */
819     @FastNative
createObjectArray(Class<?> componentType, int length)820     private static native Object createObjectArray(Class<?> componentType, int length)
821             throws NegativeArraySizeException;
822 
notAnArray(Object o)823     private static IllegalArgumentException notAnArray(Object o) {
824         throw new IllegalArgumentException("Not an array: " + o.getClass());
825     }
826 
incompatibleType(Object o)827     private static IllegalArgumentException incompatibleType(Object o) {
828         throw new IllegalArgumentException("Array has incompatible type: " + o.getClass());
829     }
830 
badArray(Object array)831     private static RuntimeException badArray(Object array) {
832         if (array == null) {
833             throw new NullPointerException("array == null");
834         } else if (!array.getClass().isArray()) {
835             throw notAnArray(array);
836         } else {
837             throw incompatibleType(array);
838         }
839     }
840     // END Android-added: Helper methods to support custom method implementations.
841 }
842