GNU Classpath (0.95) | |
Frames | No Frames |
1: /* java.lang.reflect.Array - manipulate arrays by reflection 2: Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 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. 10: 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. 15: 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. 20: 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. 25: 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. */ 37: 38: 39: package java.lang.reflect; 40: 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> 47: * 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> 56: * 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. 62: * 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 76: */ 77: public final class Array 78: { 79: 80: /** 81: * This class is uninstantiable. 82: */ 83: private Array() 84: { 85: } 86: 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 97: */ 98: public static Object newInstance(Class<?> componentType, int length) 99: { 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(); 120: } 121: 122: /** 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! 130: * 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 145: */ 146: public static Object newInstance(Class<?> componentType, int[] dimensions) 147: { 148: if (dimensions.length <= 0) 149: throw new IllegalArgumentException ("Empty dimensions array."); 150: return createMultiArray(componentType, dimensions, 151: dimensions.length - 1); 152: } 153: 154: /** 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 160: */ 161: public static int getLength(Object array) 162: { 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(); 184: } 185: 186: /** 187: * Gets an element of an array. Primitive elements will be wrapped in 188: * the corresponding class type. 189: * 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) 205: */ 206: public static Object get(Object array, int index) 207: { 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(); 229: } 230: 231: /** 232: * Gets an element of a boolean array. 233: * 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) 243: */ 244: public static boolean getBoolean(Object array, int index) 245: { 246: if (array instanceof boolean[]) 247: return ((boolean[]) array)[index]; 248: if (array == null) 249: throw new NullPointerException(); 250: throw new IllegalArgumentException(); 251: } 252: 253: /** 254: * Gets an element of a byte array. 255: * 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) 265: */ 266: public static byte getByte(Object array, int index) 267: { 268: if (array instanceof byte[]) 269: return ((byte[]) array)[index]; 270: if (array == null) 271: throw new NullPointerException(); 272: throw new IllegalArgumentException(); 273: } 274: 275: /** 276: * Gets an element of a char array. 277: * 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) 287: */ 288: public static char getChar(Object array, int index) 289: { 290: if (array instanceof char[]) 291: return ((char[]) array)[index]; 292: if (array == null) 293: throw new NullPointerException(); 294: throw new IllegalArgumentException(); 295: } 296: 297: /** 298: * Gets an element of a short array. 299: * 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) 309: */ 310: public static short getShort(Object array, int index) 311: { 312: if (array instanceof short[]) 313: return ((short[]) array)[index]; 314: return getByte(array, index); 315: } 316: 317: /** 318: * Gets an element of an int array. 319: * 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) 329: */ 330: public static int getInt(Object array, int index) 331: { 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); 337: } 338: 339: /** 340: * Gets an element of a long array. 341: * 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) 351: */ 352: public static long getLong(Object array, int index) 353: { 354: if (array instanceof long[]) 355: return ((long[]) array)[index]; 356: return getInt(array, index); 357: } 358: 359: /** 360: * Gets an element of a float array. 361: * 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) 371: */ 372: public static float getFloat(Object array, int index) 373: { 374: if (array instanceof float[]) 375: return ((float[]) array)[index]; 376: return getLong(array, index); 377: } 378: 379: /** 380: * Gets an element of a double array. 381: * 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) 391: */ 392: public static double getDouble(Object array, int index) 393: { 394: if (array instanceof double[]) 395: return ((double[]) array)[index]; 396: return getFloat(array, index); 397: } 398: 399: /** 400: * Sets an element of an array. If the array is primitive, then the new 401: * value is unwrapped and widened. 402: * 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) 421: */ 422: public static void set(Object array, int index, Object value) 423: { 424: if (array instanceof Object[]) 425: { 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; 431: } 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(); 452: } 453: 454: /** 455: * Sets an element of a boolean array. 456: * 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) 466: */ 467: public static void setBoolean(Object array, int index, boolean value) 468: { 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(); 475: } 476: 477: /** 478: * Sets an element of a byte array. 479: * 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) 489: */ 490: public static void setByte(Object array, int index, byte value) 491: { 492: if (array instanceof byte[]) 493: ((byte[]) array)[index] = value; 494: else 495: setShort(array, index, value); 496: } 497: 498: /** 499: * Sets an element of a char array. 500: * 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) 510: */ 511: public static void setChar(Object array, int index, char value) 512: { 513: if (array instanceof char[]) 514: ((char[]) array)[index] = value; 515: else 516: setInt(array, index, value); 517: } 518: 519: /** 520: * Sets an element of a short array. 521: * 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) 531: */ 532: public static void setShort(Object array, int index, short value) 533: { 534: if (array instanceof short[]) 535: ((short[]) array)[index] = value; 536: else 537: setInt(array, index, value); 538: } 539: 540: /** 541: * Sets an element of an int array. 542: * 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) 552: */ 553: public static void setInt(Object array, int index, int value) 554: { 555: if (array instanceof int[]) 556: ((int[]) array)[index] = value; 557: else 558: setLong(array, index, value); 559: } 560: 561: /** 562: * Sets an element of a long array. 563: * 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) 573: */ 574: public static void setLong(Object array, int index, long value) 575: { 576: if (array instanceof long[]) 577: ((long[]) array)[index] = value; 578: else 579: setFloat(array, index, value); 580: } 581: 582: /** 583: * Sets an element of a float array. 584: * 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) 594: */ 595: public static void setFloat(Object array, int index, float value) 596: { 597: if (array instanceof float[]) 598: ((float[]) array)[index] = value; 599: else 600: setDouble(array, index, value); 601: } 602: 603: /** 604: * Sets an element of a double array. 605: * 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) 615: */ 616: public static void setDouble(Object array, int index, double value) 617: { 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(); 624: } 625: 626: /** 627: * Dynamically and recursively create a multi-dimensioned array of objects. 628: * 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 635: */ 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) 640: { 641: if (index == 0) 642: return newInstance(type, dimensions[0]); 643: 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; 654: } 655: 656: }
GNU Classpath (0.95) |