Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / java / lang / reflect / Array.java
blobae65ffbf2406867f1428e59cdf20a8dd762b1374
1 /* java.lang.reflect.Array - manipulate arrays by reflection
2 Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.lang.reflect;
41 /**
42 * Array holds static helper functions that allow you to create and
43 * manipulate arrays by reflection. Operations know how to perform widening
44 * conversions, but throw {@link IllegalArgumentException} if you attempt
45 * a narrowing conversion. Also, when accessing primitive arrays, this
46 * class performs object wrapping and unwrapping as necessary.<p>
48 * <B>Note:</B> This class returns and accepts types as Classes, even
49 * primitive types; there are Class types defined that represent each
50 * different primitive type. They are <code>java.lang.Boolean.TYPE,
51 * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
52 * byte.class</code>, etc. These are not to be confused with the
53 * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
54 * real classes. Note also that the shorthand <code>Object[].class</code>
55 * is a convenient way to get array Classes.<p>
57 * <B>Performance note:</B> This class performs best when it does not have
58 * to convert primitive types. The further along the chain it has to convert,
59 * the worse performance will be. You're best off using the array as whatever
60 * type it already is, and then converting the result. You will do even
61 * worse if you do this and use the generic set() function.
63 * @author John Keiser
64 * @author Eric Blake (ebb9@email.byu.edu)
65 * @author Per Bothner (bothner@cygnus.com)
66 * @see java.lang.Boolean#TYPE
67 * @see java.lang.Byte#TYPE
68 * @see java.lang.Short#TYPE
69 * @see java.lang.Character#TYPE
70 * @see java.lang.Integer#TYPE
71 * @see java.lang.Long#TYPE
72 * @see java.lang.Float#TYPE
73 * @see java.lang.Double#TYPE
74 * @since 1.1
75 * @status updated to 1.4
77 public final class Array
80 /**
81 * This class is uninstantiable.
83 private Array()
87 /**
88 * Creates a new single-dimensioned array.
89 * @param componentType the type of the array to create
90 * @param length the length of the array to create
91 * @return the created array, cast to an Object
92 * @throws NullPointerException if <code>componentType</code> is null
93 * @throws IllegalArgumentException if <code>componentType</code> is
94 * <code>Void.TYPE</code>
95 * @throws NegativeArraySizeException when length is less than 0
96 * @throws OutOfMemoryError if memory allocation fails
98 public static Object newInstance(Class componentType, int length)
100 if (! componentType.isPrimitive())
101 return VMArray.createObjectArray(componentType, length);
102 if (componentType == boolean.class)
103 return new boolean[length];
104 if (componentType == byte.class)
105 return new byte[length];
106 if (componentType == char.class)
107 return new char[length];
108 if (componentType == short.class)
109 return new short[length];
110 if (componentType == int.class)
111 return new int[length];
112 if (componentType == long.class)
113 return new long[length];
114 if (componentType == float.class)
115 return new float[length];
116 if (componentType == double.class)
117 return new double[length];
118 // assert componentType == void.class
119 throw new IllegalArgumentException();
123 * Creates a new multi-dimensioned array. The new array has the same
124 * component type as the argument class, and the number of dimensions
125 * in the new array is the sum of the dimensions of the argument class
126 * and the length of the argument dimensions. Virtual Machine limitations
127 * forbid too many dimensions (usually 255 is the maximum); but even
128 * 50 dimensions of 2 elements in each dimension would exceed your memory
129 * long beforehand!
131 * @param componentType the type of the array to create.
132 * @param dimensions the dimensions of the array to create. Each element
133 * in <code>dimensions</code> makes another dimension of the new
134 * array. Thus, <code>Array.newInstance(java.lang.Boolean,
135 * new int[]{1,2,3})</code> is the same as
136 * <code>new java.lang.Boolean[1][2][3]</code>
137 * @return the created array, cast to an Object
138 * @throws NullPointerException if componentType or dimension is null
139 * @throws IllegalArgumentException if the the size of
140 * <code>dimensions</code> is 0 or exceeds the maximum number of
141 * array dimensions in the VM; or if componentType is Void.TYPE
142 * @throws NegativeArraySizeException when any of the dimensions is less
143 * than 0
144 * @throws OutOfMemoryError if memory allocation fails
146 public static Object newInstance(Class componentType, int[] dimensions)
148 if (dimensions.length <= 0)
149 throw new IllegalArgumentException ("Empty dimensions array.");
150 return createMultiArray(componentType, dimensions,
151 dimensions.length - 1);
155 * Gets the array length.
156 * @param array the array
157 * @return the length of the array
158 * @throws IllegalArgumentException if <code>array</code> is not an array
159 * @throws NullPointerException if <code>array</code> is null
161 public static int getLength(Object array)
163 if (array instanceof Object[])
164 return ((Object[]) array).length;
165 if (array instanceof boolean[])
166 return ((boolean[]) array).length;
167 if (array instanceof byte[])
168 return ((byte[]) array). length;
169 if (array instanceof char[])
170 return ((char[]) array).length;
171 if (array instanceof short[])
172 return ((short[]) array).length;
173 if (array instanceof int[])
174 return ((int[]) array).length;
175 if (array instanceof long[])
176 return ((long[]) array).length;
177 if (array instanceof float[])
178 return ((float[]) array).length;
179 if (array instanceof double[])
180 return ((double[]) array).length;
181 if (array == null)
182 throw new NullPointerException();
183 throw new IllegalArgumentException();
187 * Gets an element of an array. Primitive elements will be wrapped in
188 * the corresponding class type.
190 * @param array the array to access
191 * @param index the array index to access
192 * @return the element at <code>array[index]</code>
193 * @throws IllegalArgumentException if <code>array</code> is not an array
194 * @throws NullPointerException if <code>array</code> is null
195 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
196 * bounds
197 * @see #getBoolean(Object, int)
198 * @see #getByte(Object, int)
199 * @see #getChar(Object, int)
200 * @see #getShort(Object, int)
201 * @see #getInt(Object, int)
202 * @see #getLong(Object, int)
203 * @see #getFloat(Object, int)
204 * @see #getDouble(Object, int)
206 public static Object get(Object array, int index)
208 if (array instanceof Object[])
209 return ((Object[]) array)[index];
210 if (array instanceof boolean[])
211 return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE;
212 if (array instanceof byte[])
213 return new Byte(((byte[]) array)[index]);
214 if (array instanceof char[])
215 return new Character(((char[]) array)[index]);
216 if (array instanceof short[])
217 return new Short(((short[]) array)[index]);
218 if (array instanceof int[])
219 return new Integer(((int[]) array)[index]);
220 if (array instanceof long[])
221 return new Long(((long[]) array)[index]);
222 if (array instanceof float[])
223 return new Float(((float[]) array)[index]);
224 if (array instanceof double[])
225 return new Double(((double[]) array)[index]);
226 if (array == null)
227 throw new NullPointerException();
228 throw new IllegalArgumentException();
232 * Gets an element of a boolean array.
234 * @param array the array to access
235 * @param index the array index to access
236 * @return the boolean element at <code>array[index]</code>
237 * @throws IllegalArgumentException if <code>array</code> is not a boolean
238 * array
239 * @throws NullPointerException if <code>array</code> is null
240 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
241 * bounds
242 * @see #get(Object, int)
244 public static boolean getBoolean(Object array, int index)
246 if (array instanceof boolean[])
247 return ((boolean[]) array)[index];
248 if (array == null)
249 throw new NullPointerException();
250 throw new IllegalArgumentException();
254 * Gets an element of a byte array.
256 * @param array the array to access
257 * @param index the array index to access
258 * @return the byte element at <code>array[index]</code>
259 * @throws IllegalArgumentException if <code>array</code> is not a byte
260 * array
261 * @throws NullPointerException if <code>array</code> is null
262 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
263 * bounds
264 * @see #get(Object, int)
266 public static byte getByte(Object array, int index)
268 if (array instanceof byte[])
269 return ((byte[]) array)[index];
270 if (array == null)
271 throw new NullPointerException();
272 throw new IllegalArgumentException();
276 * Gets an element of a char array.
278 * @param array the array to access
279 * @param index the array index to access
280 * @return the char element at <code>array[index]</code>
281 * @throws IllegalArgumentException if <code>array</code> is not a char
282 * array
283 * @throws NullPointerException if <code>array</code> is null
284 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
285 * bounds
286 * @see #get(Object, int)
288 public static char getChar(Object array, int index)
290 if (array instanceof char[])
291 return ((char[]) array)[index];
292 if (array == null)
293 throw new NullPointerException();
294 throw new IllegalArgumentException();
298 * Gets an element of a short array.
300 * @param array the array to access
301 * @param index the array index to access
302 * @return the short element at <code>array[index]</code>
303 * @throws IllegalArgumentException if <code>array</code> is not a byte
304 * or char array
305 * @throws NullPointerException if <code>array</code> is null
306 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
307 * bounds
308 * @see #get(Object, int)
310 public static short getShort(Object array, int index)
312 if (array instanceof short[])
313 return ((short[]) array)[index];
314 return getByte(array, index);
318 * Gets an element of an int array.
320 * @param array the array to access
321 * @param index the array index to access
322 * @return the int element at <code>array[index]</code>
323 * @throws IllegalArgumentException if <code>array</code> is not a byte,
324 * char, short, or int array
325 * @throws NullPointerException if <code>array</code> is null
326 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
327 * bounds
328 * @see #get(Object, int)
330 public static int getInt(Object array, int index)
332 if (array instanceof int[])
333 return ((int[]) array)[index];
334 if (array instanceof char[])
335 return ((char[]) array)[index];
336 return getShort(array, index);
340 * Gets an element of a long array.
342 * @param array the array to access
343 * @param index the array index to access
344 * @return the long element at <code>array[index]</code>
345 * @throws IllegalArgumentException if <code>array</code> is not a byte,
346 * char, short, int, or long array
347 * @throws NullPointerException if <code>array</code> is null
348 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
349 * bounds
350 * @see #get(Object, int)
352 public static long getLong(Object array, int index)
354 if (array instanceof long[])
355 return ((long[]) array)[index];
356 return getInt(array, index);
360 * Gets an element of a float array.
362 * @param array the array to access
363 * @param index the array index to access
364 * @return the float element at <code>array[index]</code>
365 * @throws IllegalArgumentException if <code>array</code> is not a byte,
366 * char, short, int, long, or float array
367 * @throws NullPointerException if <code>array</code> is null
368 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
369 * bounds
370 * @see #get(Object, int)
372 public static float getFloat(Object array, int index)
374 if (array instanceof float[])
375 return ((float[]) array)[index];
376 return getLong(array, index);
380 * Gets an element of a double array.
382 * @param array the array to access
383 * @param index the array index to access
384 * @return the double element at <code>array[index]</code>
385 * @throws IllegalArgumentException if <code>array</code> is not a byte,
386 * char, short, int, long, float, or double array
387 * @throws NullPointerException if <code>array</code> is null
388 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
389 * bounds
390 * @see #get(Object, int)
392 public static double getDouble(Object array, int index)
394 if (array instanceof double[])
395 return ((double[]) array)[index];
396 return getFloat(array, index);
400 * Sets an element of an array. If the array is primitive, then the new
401 * value is unwrapped and widened.
403 * @param array the array to set a value of
404 * @param index the array index to set the value to
405 * @param value the value to set
406 * @throws IllegalArgumentException if <code>array</code> is not an array,
407 * or the array is primitive and unwrapping value fails, or the
408 * value is not assignable to the array component type
409 * @throws NullPointerException if array is null, or if array is primitive
410 * and value is null
411 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
412 * bounds
413 * @see #setBoolean(Object, int, boolean)
414 * @see #setByte(Object, int, byte)
415 * @see #setChar(Object, int, char)
416 * @see #setShort(Object, int, short)
417 * @see #setInt(Object, int, int)
418 * @see #setLong(Object, int, long)
419 * @see #setFloat(Object, int, float)
420 * @see #setDouble(Object, int, double)
422 public static void set(Object array, int index, Object value)
424 if (array instanceof Object[])
426 // Too bad the API won't let us throw the easier ArrayStoreException!
427 if (value != null
428 && ! array.getClass().getComponentType().isInstance(value))
429 throw new IllegalArgumentException();
430 ((Object[]) array)[index] = value;
432 else if (value instanceof Byte)
433 setByte(array, index, ((Byte) value).byteValue());
434 else if (value instanceof Short)
435 setShort(array, index, ((Short) value).shortValue());
436 else if (value instanceof Integer)
437 setInt(array, index, ((Integer) value).intValue());
438 else if (value instanceof Long)
439 setLong(array, index, ((Long) value).longValue());
440 else if (value instanceof Float)
441 setFloat(array, index, ((Float) value).floatValue());
442 else if (value instanceof Double)
443 setDouble(array, index, ((Double) value).doubleValue());
444 else if (value instanceof Character)
445 setChar(array, index, ((Character) value).charValue());
446 else if (value instanceof Boolean)
447 setBoolean(array, index, ((Boolean) value).booleanValue());
448 else if (array == null)
449 throw new NullPointerException();
450 else
451 throw new IllegalArgumentException();
455 * Sets an element of a boolean array.
457 * @param array the array to set a value of
458 * @param index the array index to set the value to
459 * @param value the value to set
460 * @throws IllegalArgumentException if <code>array</code> is not a boolean
461 * array
462 * @throws NullPointerException if <code>array</code> is null
463 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
464 * bounds
465 * @see #set(Object, int, Object)
467 public static void setBoolean(Object array, int index, boolean value)
469 if (array instanceof boolean[])
470 ((boolean[]) array)[index] = value;
471 else if (array == null)
472 throw new NullPointerException();
473 else
474 throw new IllegalArgumentException();
478 * Sets an element of a byte array.
480 * @param array the array to set a value of
481 * @param index the array index to set the value to
482 * @param value the value to set
483 * @throws IllegalArgumentException if <code>array</code> is not a byte,
484 * short, int, long, float, or double array
485 * @throws NullPointerException if <code>array</code> is null
486 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
487 * bounds
488 * @see #set(Object, int, Object)
490 public static void setByte(Object array, int index, byte value)
492 if (array instanceof byte[])
493 ((byte[]) array)[index] = value;
494 else
495 setShort(array, index, value);
499 * Sets an element of a char array.
501 * @param array the array to set a value of
502 * @param index the array index to set the value to
503 * @param value the value to set
504 * @throws IllegalArgumentException if <code>array</code> is not a char,
505 * int, long, float, or double array
506 * @throws NullPointerException if <code>array</code> is null
507 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
508 * bounds
509 * @see #set(Object, int, Object)
511 public static void setChar(Object array, int index, char value)
513 if (array instanceof char[])
514 ((char[]) array)[index] = value;
515 else
516 setInt(array, index, value);
520 * Sets an element of a short array.
522 * @param array the array to set a value of
523 * @param index the array index to set the value to
524 * @param value the value to set
525 * @throws IllegalArgumentException if <code>array</code> is not a short,
526 * int, long, float, or double array
527 * @throws NullPointerException if <code>array</code> is null
528 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
529 * bounds
530 * @see #set(Object, int, Object)
532 public static void setShort(Object array, int index, short value)
534 if (array instanceof short[])
535 ((short[]) array)[index] = value;
536 else
537 setInt(array, index, value);
541 * Sets an element of an int array.
543 * @param array the array to set a value of
544 * @param index the array index to set the value to
545 * @param value the value to set
546 * @throws IllegalArgumentException if <code>array</code> is not an int,
547 * long, float, or double array
548 * @throws NullPointerException if <code>array</code> is null
549 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
550 * bounds
551 * @see #set(Object, int, Object)
553 public static void setInt(Object array, int index, int value)
555 if (array instanceof int[])
556 ((int[]) array)[index] = value;
557 else
558 setLong(array, index, value);
562 * Sets an element of a long array.
564 * @param array the array to set a value of
565 * @param index the array index to set the value to
566 * @param value the value to set
567 * @throws IllegalArgumentException if <code>array</code> is not a long,
568 * float, or double array
569 * @throws NullPointerException if <code>array</code> is null
570 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
571 * bounds
572 * @see #set(Object, int, Object)
574 public static void setLong(Object array, int index, long value)
576 if (array instanceof long[])
577 ((long[]) array)[index] = value;
578 else
579 setFloat(array, index, value);
583 * Sets an element of a float array.
585 * @param array the array to set a value of
586 * @param index the array index to set the value to
587 * @param value the value to set
588 * @throws IllegalArgumentException if <code>array</code> is not a float
589 * or double array
590 * @throws NullPointerException if <code>array</code> is null
591 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
592 * bounds
593 * @see #set(Object, int, Object)
595 public static void setFloat(Object array, int index, float value)
597 if (array instanceof float[])
598 ((float[]) array)[index] = value;
599 else
600 setDouble(array, index, value);
604 * Sets an element of a double array.
606 * @param array the array to set a value of
607 * @param index the array index to set the value to
608 * @param value the value to set
609 * @throws IllegalArgumentException if <code>array</code> is not a double
610 * array
611 * @throws NullPointerException if <code>array</code> is null
612 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
613 * bounds
614 * @see #set(Object, int, Object)
616 public static void setDouble(Object array, int index, double value)
618 if (array instanceof double[])
619 ((double[]) array)[index] = value;
620 else if (array == null)
621 throw new NullPointerException();
622 else
623 throw new IllegalArgumentException();
627 * Dynamically and recursively create a multi-dimensioned array of objects.
629 * @param type guaranteed to be a valid object type
630 * @param dimensions the dimensions of the array
631 * @param index index of the current dimension to build
632 * @return the new multi-dimensioned array
633 * @throws NegativeArraySizeException if any entry of dimensions is negative
634 * @throws OutOfMemoryError if memory allocation fails
636 // This would be faster if implemented natively, using the multianewarray
637 // bytecode instead of this recursive call
638 private static Object createMultiArray(Class type, int[] dimensions,
639 int index)
641 if (index == 0)
642 return newInstance(type, dimensions[0]);
644 Object toAdd = createMultiArray(type, dimensions, index - 1);
645 Class thisType = toAdd.getClass();
646 Object[] retval
647 = (Object[]) VMArray.createObjectArray(thisType, dimensions[index]);
648 if (dimensions[index] > 0)
649 retval[0] = toAdd;
650 int i = dimensions[index];
651 while (--i > 0)
652 retval[i] = createMultiArray(type, dimensions, index - 1);
653 return retval;