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
27package java.lang.reflect;
28
29import 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 */
41public final
42class Array {
43
44    /**
45     * Constructor.  Class Array is not instantiable.
46     */
47    private Array() {}
48
49    /**
50     * Creates a new array with the specified component type and
51     * length.
52     * Invoking this method is equivalent to creating an array
53     * as follows:
54     * <blockquote>
55     * <pre>
56     * int[] x = {length};
57     * Array.newInstance(componentType, x);
58     * </pre>
59     * </blockquote>
60     * <p>The number of dimensions of the new array must not
61     * exceed 255.
62     *
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
70     * Void#TYPE} or if the number of dimensions of the requested array
71     * instance exceed 255.
72     * @exception NegativeArraySizeException if the specified {@code length}
73     * is negative
74     */
75    public static Object newInstance(Class<?> componentType, int length)
76        throws NegativeArraySizeException {
77        return newArray(componentType, length);
78    }
79
80    /**
81     * Creates a new array
82     * with the specified component type and dimensions.
83     * If {@code componentType}
84     * represents a non-array class or interface, the new array
85     * has {@code dimensions.length} dimensions and
86     * {@code componentType} as its component type. If
87     * {@code componentType} represents an array class, the
88     * number of dimensions of the new array is equal to the sum
89     * of {@code dimensions.length} and the number of
90     * dimensions of {@code componentType}. In this case, the
91     * component type of the new array is the component type of
92     * {@code componentType}.
93     *
94     * <p>The number of dimensions of the new array must not
95     * exceed 255.
96     *
97     * @param componentType the {@code Class} object representing the component
98     * type of the new array
99     * @param dimensions an array of {@code int} representing the dimensions of
100     * the new array
101     * @return the new array
102     * @exception NullPointerException if the specified
103     * {@code componentType} argument is null
104     * @exception IllegalArgumentException if the specified {@code dimensions}
105     * argument is a zero-dimensional array, if componentType is {@link
106     * Void#TYPE}, or if the number of dimensions of the requested array
107     * instance exceed 255.
108     * @exception NegativeArraySizeException if any of the components in
109     * the specified {@code dimensions} argument is negative.
110     */
111    public static Object newInstance(Class<?> componentType, int... dimensions)
112        throws IllegalArgumentException, NegativeArraySizeException {
113        if (dimensions.length <= 0 || dimensions.length > 255) {
114            throw new IllegalArgumentException("Bad number of dimensions: " + dimensions.length);
115        }
116        if (componentType == void.class) {
117            throw new IllegalArgumentException("Can't allocate an array of void");
118        }
119        if (componentType == null) {
120            throw new NullPointerException("componentType == null");
121        }
122        return createMultiArray(componentType, dimensions);
123    }
124
125    /**
126     * Returns the length of the specified array object, as an {@code int}.
127     *
128     * @param array the array
129     * @return the length of the array
130     * @exception IllegalArgumentException if the object argument is not
131     * an array
132     */
133    public static int getLength(Object array) {
134        if (array instanceof Object[]) {
135            return ((Object[]) array).length;
136        } else if (array instanceof boolean[]) {
137            return ((boolean[]) array).length;
138        } else if (array instanceof byte[]) {
139            return ((byte[]) array).length;
140        } else if (array instanceof char[]) {
141            return ((char[]) array).length;
142        } else if (array instanceof double[]) {
143            return ((double[]) array).length;
144        } else if (array instanceof float[]) {
145            return ((float[]) array).length;
146        } else if (array instanceof int[]) {
147            return ((int[]) array).length;
148        } else if (array instanceof long[]) {
149            return ((long[]) array).length;
150        } else if (array instanceof short[]) {
151            return ((short[]) array).length;
152        }
153        throw badArray(array);
154      }
155
156    /**
157     * Returns the value of the indexed component in the specified
158     * array object.  The value is automatically wrapped in an object
159     * if it has a primitive type.
160     *
161     * @param array the array
162     * @param index the index
163     * @return the (possibly wrapped) value of the indexed component in
164     * the specified array
165     * @exception NullPointerException If the specified object is null
166     * @exception IllegalArgumentException If the specified object is not
167     * an array
168     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
169     * argument is negative, or if it is greater than or equal to the
170     * length of the specified array
171     */
172    public static Object get(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
173        if (array instanceof Object[]) {
174            return ((Object[]) array)[index];
175        }
176        if (array instanceof boolean[]) {
177            return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE;
178        }
179        if (array instanceof byte[]) {
180            return Byte.valueOf(((byte[]) array)[index]);
181        }
182        if (array instanceof char[]) {
183            return Character.valueOf(((char[]) array)[index]);
184        }
185        if (array instanceof short[]) {
186            return Short.valueOf(((short[]) array)[index]);
187        }
188        if (array instanceof int[]) {
189            return Integer.valueOf(((int[]) array)[index]);
190        }
191        if (array instanceof long[]) {
192            return Long.valueOf(((long[]) array)[index]);
193        }
194        if (array instanceof float[]) {
195            return new Float(((float[]) array)[index]);
196        }
197        if (array instanceof double[]) {
198            return new Double(((double[]) array)[index]);
199        }
200        if (array == null) {
201            throw new NullPointerException("array == null");
202        }
203        throw notAnArray(array);
204    }
205
206    /**
207     * Returns the value of the indexed component in the specified
208     * array object, as a {@code boolean}.
209     *
210     * @param array the array
211     * @param index the index
212     * @return the value of the indexed component in the specified array
213     * @exception NullPointerException If the specified object is null
214     * @exception IllegalArgumentException If the specified object is not
215     * an array, or if the indexed element cannot be converted to the
216     * return type by an identity or widening conversion
217     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
218     * argument is negative, or if it is greater than or equal to the
219     * length of the specified array
220     * @see Array#get
221     */
222    public static boolean getBoolean(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
223        if (array instanceof boolean[]) {
224            return ((boolean[]) array)[index];
225        }
226        throw badArray(array);
227    }
228
229    /**
230     * Returns the value of the indexed component in the specified
231     * array object, as a {@code byte}.
232     *
233     * @param array the array
234     * @param index the index
235     * @return the value of the indexed component in the specified array
236     * @exception NullPointerException If the specified object is null
237     * @exception IllegalArgumentException If the specified object is not
238     * an array, or if the indexed element cannot be converted to the
239     * return type by an identity or widening conversion
240     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
241     * argument is negative, or if it is greater than or equal to the
242     * length of the specified array
243     * @see Array#get
244     */
245    public static byte getByte(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
246        if (array instanceof byte[]) {
247            return ((byte[]) array)[index];
248        }
249        throw badArray(array);
250    }
251
252    /**
253     * Returns the value of the indexed component in the specified
254     * array object, as a {@code char}.
255     *
256     * @param array the array
257     * @param index the index
258     * @return the value of the indexed component in the specified array
259     * @exception NullPointerException If the specified object is null
260     * @exception IllegalArgumentException If the specified object is not
261     * an array, or if the indexed element cannot be converted to the
262     * return type by an identity or widening conversion
263     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
264     * argument is negative, or if it is greater than or equal to the
265     * length of the specified array
266     * @see Array#get
267     */
268    public static char getChar(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
269        if (array instanceof char[]) {
270            return ((char[]) array)[index];
271        }
272        throw badArray(array);
273    }
274
275    /**
276     * Returns the value of the indexed component in the specified
277     * array object, as a {@code short}.
278     *
279     * @param array the array
280     * @param index the index
281     * @return the value of the indexed component in the specified array
282     * @exception NullPointerException If the specified object is null
283     * @exception IllegalArgumentException If the specified object is not
284     * an array, or if the indexed element cannot be converted to the
285     * return type by an identity or widening conversion
286     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
287     * argument is negative, or if it is greater than or equal to the
288     * length of the specified array
289     * @see Array#get
290     */
291    public static short getShort(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
292        if (array instanceof short[]) {
293            return ((short[]) array)[index];
294        } else if (array instanceof byte[]) {
295            return ((byte[]) array)[index];
296        }
297        throw badArray(array);
298    }
299
300    /**
301     * Returns the value of the indexed component in the specified
302     * array object, as an {@code int}.
303     *
304     * @param array the array
305     * @param index the index
306     * @return the value of the indexed component in the specified array
307     * @exception NullPointerException If the specified object is null
308     * @exception IllegalArgumentException If the specified object is not
309     * an array, or if the indexed element cannot be converted to the
310     * return type by an identity or widening conversion
311     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
312     * argument is negative, or if it is greater than or equal to the
313     * length of the specified array
314     * @see Array#get
315     */
316    public static int getInt(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
317        if (array instanceof int[]) {
318            return ((int[]) array)[index];
319        } else if (array instanceof byte[]) {
320            return ((byte[]) array)[index];
321        } else if (array instanceof char[]) {
322            return ((char[]) array)[index];
323        } else if (array instanceof short[]) {
324            return ((short[]) array)[index];
325        }
326        throw badArray(array);
327    }
328
329    /**
330     * Returns the value of the indexed component in the specified
331     * array object, as a {@code long}.
332     *
333     * @param array the array
334     * @param index the index
335     * @return the value of the indexed component in the specified array
336     * @exception NullPointerException If the specified object is null
337     * @exception IllegalArgumentException If the specified object is not
338     * an array, or if the indexed element cannot be converted to the
339     * return type by an identity or widening conversion
340     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
341     * argument is negative, or if it is greater than or equal to the
342     * length of the specified array
343     * @see Array#get
344     */
345    public static long getLong(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
346        if (array instanceof long[]) {
347            return ((long[]) array)[index];
348        } else if (array instanceof byte[]) {
349            return ((byte[]) array)[index];
350        } else if (array instanceof char[]) {
351            return ((char[]) array)[index];
352        } else if (array instanceof int[]) {
353            return ((int[]) array)[index];
354        } else if (array instanceof short[]) {
355            return ((short[]) array)[index];
356        }
357        throw badArray(array);
358    }
359
360    /**
361     * Returns the value of the indexed component in the specified
362     * array object, as a {@code float}.
363     *
364     * @param array the array
365     * @param index the index
366     * @return the value of the indexed component in the specified array
367     * @exception NullPointerException If the specified object is null
368     * @exception IllegalArgumentException If the specified object is not
369     * an array, or if the indexed element cannot be converted to the
370     * return type by an identity or widening conversion
371     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
372     * argument is negative, or if it is greater than or equal to the
373     * length of the specified array
374     * @see Array#get
375     */
376    public static float getFloat(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
377        if (array instanceof float[]) {
378            return ((float[]) array)[index];
379        } else if (array instanceof byte[]) {
380            return ((byte[]) array)[index];
381        } else if (array instanceof char[]) {
382            return ((char[]) array)[index];
383        } else if (array instanceof int[]) {
384            return ((int[]) array)[index];
385        } else if (array instanceof long[]) {
386            return ((long[]) array)[index];
387        } else if (array instanceof short[]) {
388            return ((short[]) array)[index];
389        }
390        throw badArray(array);
391    }
392
393    /**
394     * Returns the value of the indexed component in the specified
395     * array object, as a {@code double}.
396     *
397     * @param array the array
398     * @param index the index
399     * @return the value of the indexed component in the specified array
400     * @exception NullPointerException If the specified object is null
401     * @exception IllegalArgumentException If the specified object is not
402     * an array, or if the indexed element cannot be converted to the
403     * return type by an identity or widening conversion
404     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
405     * argument is negative, or if it is greater than or equal to the
406     * length of the specified array
407     * @see Array#get
408     */
409    public static double getDouble(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
410        if (array instanceof double[]) {
411            return ((double[]) array)[index];
412        } else if (array instanceof byte[]) {
413            return ((byte[]) array)[index];
414        } else if (array instanceof char[]) {
415            return ((char[]) array)[index];
416        } else if (array instanceof float[]) {
417            return ((float[]) array)[index];
418        } else if (array instanceof int[]) {
419            return ((int[]) array)[index];
420        } else if (array instanceof long[]) {
421            return ((long[]) array)[index];
422        } else if (array instanceof short[]) {
423            return ((short[]) array)[index];
424        }
425        throw badArray(array);
426    }
427
428    /**
429     * Sets the value of the indexed component of the specified array
430     * object to the specified new value.  The new value is first
431     * automatically unwrapped if the array has a primitive component
432     * type.
433     * @param array the array
434     * @param index the index into the array
435     * @param value the new value of the indexed component
436     * @exception NullPointerException If the specified object argument
437     * is null
438     * @exception IllegalArgumentException If the specified object argument
439     * is not an array, or if the array component type is primitive and
440     * an unwrapping conversion fails
441     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
442     * argument is negative, or if it is greater than or equal to
443     * the length of the specified array
444     */
445    public static void set(Object array, int index, Object value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
446        if (!array.getClass().isArray()) {
447            throw notAnArray(array);
448        }
449
450        if (array instanceof Object[]) {
451            if (value != null && !array.getClass().getComponentType().isInstance(value)) {
452                throw incompatibleType(array);
453            }
454            ((Object[]) array)[index] = value;
455        } else {
456            if (value == null) {
457                throw new IllegalArgumentException("Primitive array can't take null values.");
458            }
459            if (value instanceof Boolean) {
460                setBoolean(array, index, ((Boolean) value).booleanValue());
461            } else if (value instanceof Byte) {
462                setByte(array, index, ((Byte) value).byteValue());
463            } else if (value instanceof Character) {
464                setChar(array, index, ((Character) value).charValue());
465            } else if (value instanceof Short) {
466                setShort(array, index, ((Short) value).shortValue());
467            } else if (value instanceof Integer) {
468                setInt(array, index, ((Integer) value).intValue());
469            } else if (value instanceof Long) {
470                setLong(array, index, ((Long) value).longValue());
471            } else if (value instanceof Float) {
472                setFloat(array, index, ((Float) value).floatValue());
473            } else if (value instanceof Double) {
474                setDouble(array, index, ((Double) value).doubleValue());
475            }
476        }
477    }
478
479    /**
480     * Sets the value of the indexed component of the specified array
481     * object to the specified {@code boolean} value.
482     * @param array the array
483     * @param index the index into the array
484     * @param value the new value of the indexed component
485     * @exception NullPointerException If the specified object argument
486     * is null
487     * @exception IllegalArgumentException If the specified object argument
488     * is not an array, or if the specified value cannot be converted
489     * to the underlying array's component type by an identity or a
490     * primitive widening conversion
491     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
492     * argument is negative, or if it is greater than or equal to
493     * the length of the specified array
494     * @see Array#set
495     */
496    // Android-changed param name s/z/value
497    public static void setBoolean(Object array, int index, boolean value) {
498        if (array instanceof boolean[]) {
499            ((boolean[]) array)[index] = value;
500        } else {
501            throw badArray(array);
502        }
503    }
504
505    /**
506     * Sets the value of the indexed component of the specified array
507     * object to the specified {@code byte} value.
508     * @param array the array
509     * @param index the index into the array
510     * @param value 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 param name s/b/value
523    public static void setByte(Object array, int index, byte value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
524        if (array instanceof byte[]) {
525            ((byte[]) array)[index] = value;
526        } else if (array instanceof double[]) {
527            ((double[]) array)[index] = value;
528        } else if (array instanceof float[]) {
529            ((float[]) array)[index] = value;
530        } else if (array instanceof int[]) {
531            ((int[]) array)[index] = value;
532        } else if (array instanceof long[]) {
533            ((long[]) array)[index] = value;
534        } else if (array instanceof short[]) {
535            ((short[]) array)[index] = value;
536        } else {
537            throw badArray(array);
538        }
539    }
540
541    /**
542     * Sets the value of the indexed component of the specified array
543     * object to the specified {@code char} value.
544     * @param array the array
545     * @param index the index into the array
546     * @param value the new value of the indexed component
547     * @exception NullPointerException If the specified object argument
548     * is null
549     * @exception IllegalArgumentException If the specified object argument
550     * is not an array, or if the specified value cannot be converted
551     * to the underlying array's component type by an identity or a
552     * primitive widening conversion
553     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
554     * argument is negative, or if it is greater than or equal to
555     * the length of the specified array
556     * @see Array#set
557     */
558    // Android-changed param name s/c/value
559    public static void setChar(Object array, int index, char value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
560        if (array instanceof char[]) {
561            ((char[]) array)[index] = value;
562        } else if (array instanceof double[]) {
563            ((double[]) array)[index] = value;
564        } else if (array instanceof float[]) {
565            ((float[]) array)[index] = value;
566        } else if (array instanceof int[]) {
567            ((int[]) array)[index] = value;
568        } else if (array instanceof long[]) {
569            ((long[]) array)[index] = value;
570        } else {
571            throw badArray(array);
572        }
573    }
574
575    /**
576     * Sets the value of the indexed component of the specified array
577     * object to the specified {@code short} value.
578     * @param array the array
579     * @param index the index into the array
580     * @param value the new value of the indexed component
581     * @exception NullPointerException If the specified object argument
582     * is null
583     * @exception IllegalArgumentException If the specified object argument
584     * is not an array, or if the specified value cannot be converted
585     * to the underlying array's component type by an identity or a
586     * primitive widening conversion
587     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
588     * argument is negative, or if it is greater than or equal to
589     * the length of the specified array
590     * @see Array#set
591     */
592    // Android-changed param name s/s/value
593    public static void setShort(Object array, int index, short value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
594        if (array instanceof short[]) {
595            ((short[]) array)[index] = value;
596        } else if (array instanceof double[]) {
597            ((double[]) array)[index] = value;
598        } else if (array instanceof float[]) {
599            ((float[]) array)[index] = value;
600        } else if (array instanceof int[]) {
601            ((int[]) array)[index] = value;
602        } else if (array instanceof long[]) {
603            ((long[]) array)[index] = value;
604        } else {
605            throw badArray(array);
606        }
607    }
608
609    /**
610     * Sets the value of the indexed component of the specified array
611     * object to the specified {@code int} value.
612     * @param array the array
613     * @param index the index into the array
614     * @param value the new value of the indexed component
615     * @exception NullPointerException If the specified object argument
616     * is null
617     * @exception IllegalArgumentException If the specified object argument
618     * is not an array, or if the specified value cannot be converted
619     * to the underlying array's component type by an identity or a
620     * primitive widening conversion
621     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
622     * argument is negative, or if it is greater than or equal to
623     * the length of the specified array
624     * @see Array#set
625     */
626    // Android-changed param name s/i/value
627    public static void setInt(Object array, int index, int value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
628        if (array instanceof int[]) {
629            ((int[]) array)[index] = value;
630        } else if (array instanceof double[]) {
631            ((double[]) array)[index] = value;
632        } else if (array instanceof float[]) {
633            ((float[]) array)[index] = value;
634        } else if (array instanceof long[]) {
635            ((long[]) array)[index] = value;
636        } else {
637            throw badArray(array);
638        }
639    }
640
641    /**
642     * Sets the value of the indexed component of the specified array
643     * object to the specified {@code long} value.
644     * @param array the array
645     * @param index the index into the array
646     * @param value the new value of the indexed component
647     * @exception NullPointerException If the specified object argument
648     * is null
649     * @exception IllegalArgumentException If the specified object argument
650     * is not an array, or if the specified value cannot be converted
651     * to the underlying array's component type by an identity or a
652     * primitive widening conversion
653     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
654     * argument is negative, or if it is greater than or equal to
655     * the length of the specified array
656     * @see Array#set
657     */
658    // Android-changed param name s/l/value
659    public static void setLong(Object array, int index, long value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
660        if (array instanceof long[]) {
661            ((long[]) array)[index] = value;
662        } else if (array instanceof double[]) {
663            ((double[]) array)[index] = value;
664        } else if (array instanceof float[]) {
665            ((float[]) array)[index] = value;
666        } else {
667            throw badArray(array);
668        }
669    }
670
671    /**
672     * Sets the value of the indexed component of the specified array
673     * object to the specified {@code float} value.
674     * @param array the array
675     * @param index the index into the array
676     * @param value the new value of the indexed component
677     * @exception NullPointerException If the specified object argument
678     * is null
679     * @exception IllegalArgumentException If the specified object argument
680     * is not an array, or if the specified value cannot be converted
681     * to the underlying array's component type by an identity or a
682     * primitive widening conversion
683     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
684     * argument is negative, or if it is greater than or equal to
685     * the length of the specified array
686     * @see Array#set
687     */
688    // Android-changed param name s/f/value
689    public static void setFloat(Object array, int index, float value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
690        if (array instanceof float[]) {
691            ((float[]) array)[index] = value;
692        } else if (array instanceof double[]) {
693            ((double[]) array)[index] = value;
694        } else {
695            throw badArray(array);
696        }
697    }
698
699    /**
700     * Sets the value of the indexed component of the specified array
701     * object to the specified {@code double} value.
702     * @param array the array
703     * @param index the index into the array
704     * @param value the new value of the indexed component
705     * @exception NullPointerException If the specified object argument
706     * is null
707     * @exception IllegalArgumentException If the specified object argument
708     * is not an array, or if the specified value cannot be converted
709     * to the underlying array's component type by an identity or a
710     * primitive widening conversion
711     * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
712     * argument is negative, or if it is greater than or equal to
713     * the length of the specified array
714     * @see Array#set
715     */
716    // Android-changed param name s/d/value
717    public static void setDouble(Object array, int index, double value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
718        if (array instanceof double[]) {
719            ((double[]) array)[index] = value;
720        } else {
721            throw badArray(array);
722        }
723    }
724
725    /*
726     * Create a multi-dimensional array of objects with the specified type.
727     */
728    @FastNative
729    private static native Object createMultiArray(Class<?> componentType, int[] dimensions) throws NegativeArraySizeException;
730
731    /**
732     * Returns a new array of the specified component type and length.
733     * Equivalent to {@code new componentType[size]}.
734     *
735     * @throws NullPointerException
736     *             if the component type is null
737     * @throws NegativeArraySizeException
738     *             if {@code size < 0}
739     */
740    private static Object newArray(Class<?> componentType, int size) throws NegativeArraySizeException {
741        if (!componentType.isPrimitive()) {
742            return createObjectArray(componentType, size);
743        } else if (componentType == char.class) {
744            return new char[size];
745        } else if (componentType == int.class) {
746            return new int[size];
747        } else if (componentType == byte.class) {
748            return new byte[size];
749        } else if (componentType == boolean.class) {
750            return new boolean[size];
751        } else if (componentType == short.class) {
752            return new short[size];
753        } else if (componentType == long.class) {
754            return new long[size];
755        } else if (componentType == float.class) {
756            return new float[size];
757        } else if (componentType == double.class) {
758            return new double[size];
759        } else if (componentType == void.class) {
760            throw new IllegalArgumentException("Can't allocate an array of void");
761        }
762        throw new AssertionError();
763    }
764
765    /*
766     * Create a one-dimensional array of objects with the specified type.
767     */
768    @FastNative
769    private static native Object createObjectArray(Class<?> componentType, int length) throws NegativeArraySizeException;
770
771    private static IllegalArgumentException notAnArray(Object o) {
772        throw new IllegalArgumentException("Not an array: " + o.getClass());
773    }
774
775    private static IllegalArgumentException incompatibleType(Object o) {
776        throw new IllegalArgumentException("Array has incompatible type: " + o.getClass());
777    }
778
779    private static RuntimeException badArray(Object array) {
780        if (array == null) {
781            throw new NullPointerException("array == null");
782        } else if (!array.getClass().isArray()) {
783            throw notAnArray(array);
784        } else {
785            throw incompatibleType(array);
786        }
787    }
788}
789