GNU Classpath (0.20) | |
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: import gnu.classpath.Configuration; 42: 43: /** 44: * Array holds static helper functions that allow you to create and 45: * manipulate arrays by reflection. Operations know how to perform widening 46: * conversions, but throw {@link IllegalArgumentException} if you attempt 47: * a narrowing conversion. Also, when accessing primitive arrays, this 48: * class performs object wrapping and unwrapping as necessary.<p> 49: * 50: * <B>Note:</B> This class returns and accepts types as Classes, even 51: * primitive types; there are Class types defined that represent each 52: * different primitive type. They are <code>java.lang.Boolean.TYPE, 53: * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, 54: * byte.class</code>, etc. These are not to be confused with the 55: * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are 56: * real classes. Note also that the shorthand <code>Object[].class</code> 57: * is a convenient way to get array Classes.<p> 58: * 59: * <B>Performance note:</B> This class performs best when it does not have 60: * to convert primitive types. The further along the chain it has to convert, 61: * the worse performance will be. You're best off using the array as whatever 62: * type it already is, and then converting the result. You will do even 63: * worse if you do this and use the generic set() function. 64: * 65: * @author John Keiser 66: * @author Eric Blake (ebb9@email.byu.edu) 67: * @author Per Bothner (bothner@cygnus.com) 68: * @see java.lang.Boolean#TYPE 69: * @see java.lang.Byte#TYPE 70: * @see java.lang.Short#TYPE 71: * @see java.lang.Character#TYPE 72: * @see java.lang.Integer#TYPE 73: * @see java.lang.Long#TYPE 74: * @see java.lang.Float#TYPE 75: * @see java.lang.Double#TYPE 76: * @since 1.1 77: * @status updated to 1.4 78: */ 79: public final class Array 80: { 81: static 82: { 83: if (Configuration.INIT_LOAD_LIBRARY) 84: { 85: System.loadLibrary("javalangreflect"); 86: } 87: } 88: 89: /** 90: * This class is uninstantiable. 91: */ 92: private Array() 93: { 94: } 95: 96: /** 97: * Creates a new single-dimensioned array. 98: * @param componentType the type of the array to create 99: * @param length the length of the array to create 100: * @return the created array, cast to an Object 101: * @throws NullPointerException if <code>componentType</code> is null 102: * @throws IllegalArgumentException if <code>componentType</code> is 103: * <code>Void.TYPE</code> 104: * @throws NegativeArraySizeException when length is less than 0 105: * @throws OutOfMemoryError if memory allocation fails 106: */ 107: public static Object newInstance(Class componentType, int length) 108: { 109: if (! componentType.isPrimitive()) 110: return createObjectArray(componentType, length); 111: if (componentType == boolean.class) 112: return new boolean[length]; 113: if (componentType == byte.class) 114: return new byte[length]; 115: if (componentType == char.class) 116: return new char[length]; 117: if (componentType == short.class) 118: return new short[length]; 119: if (componentType == int.class) 120: return new int[length]; 121: if (componentType == long.class) 122: return new long[length]; 123: if (componentType == float.class) 124: return new float[length]; 125: if (componentType == double.class) 126: return new double[length]; 127: // assert componentType == void.class 128: throw new IllegalArgumentException(); 129: } 130: 131: /** 132: * Creates a new multi-dimensioned array. The new array has the same 133: * component type as the argument class, and the number of dimensions 134: * in the new array is the sum of the dimensions of the argument class 135: * and the length of the argument dimensions. Virtual Machine limitations 136: * forbid too many dimensions (usually 255 is the maximum); but even 137: * 50 dimensions of 2 elements in each dimension would exceed your memory 138: * long beforehand! 139: * 140: * @param componentType the type of the array to create. 141: * @param dimensions the dimensions of the array to create. Each element 142: * in <code>dimensions</code> makes another dimension of the new 143: * array. Thus, <code>Array.newInstance(java.lang.Boolean, 144: * new int[]{1,2,3})</code> is the same as 145: * <code>new java.lang.Boolean[1][2][3]</code> 146: * @return the created array, cast to an Object 147: * @throws NullPointerException if componentType or dimension is null 148: * @throws IllegalArgumentException if the the size of 149: * <code>dimensions</code> is 0 or exceeds the maximum number of 150: * array dimensions in the VM; or if componentType is Void.TYPE 151: * @throws NegativeArraySizeException when any of the dimensions is less 152: * than 0 153: * @throws OutOfMemoryError if memory allocation fails 154: */ 155: public static Object newInstance(Class componentType, int[] dimensions) 156: { 157: if (dimensions.length <= 0) 158: throw new IllegalArgumentException ("Empty dimensions array."); 159: return createMultiArray(componentType, dimensions, 160: dimensions.length - 1); 161: } 162: 163: /** 164: * Gets the array length. 165: * @param array the array 166: * @return the length of the array 167: * @throws IllegalArgumentException if <code>array</code> is not an array 168: * @throws NullPointerException if <code>array</code> is null 169: */ 170: public static int getLength(Object array) 171: { 172: if (array instanceof Object[]) 173: return ((Object[]) array).length; 174: if (array instanceof boolean[]) 175: return ((boolean[]) array).length; 176: if (array instanceof byte[]) 177: return ((byte[]) array). length; 178: if (array instanceof char[]) 179: return ((char[]) array).length; 180: if (array instanceof short[]) 181: return ((short[]) array).length; 182: if (array instanceof int[]) 183: return ((int[]) array).length; 184: if (array instanceof long[]) 185: return ((long[]) array).length; 186: if (array instanceof float[]) 187: return ((float[]) array).length; 188: if (array instanceof double[]) 189: return ((double[]) array).length; 190: if (array == null) 191: throw new NullPointerException(); 192: throw new IllegalArgumentException(); 193: } 194: 195: /** 196: * Gets an element of an array. Primitive elements will be wrapped in 197: * the corresponding class type. 198: * 199: * @param array the array to access 200: * @param index the array index to access 201: * @return the element at <code>array[index]</code> 202: * @throws IllegalArgumentException if <code>array</code> is not an array 203: * @throws NullPointerException if <code>array</code> is null 204: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 205: * bounds 206: * @see #getBoolean(Object, int) 207: * @see #getByte(Object, int) 208: * @see #getChar(Object, int) 209: * @see #getShort(Object, int) 210: * @see #getInt(Object, int) 211: * @see #getLong(Object, int) 212: * @see #getFloat(Object, int) 213: * @see #getDouble(Object, int) 214: */ 215: public static Object get(Object array, int index) 216: { 217: if (array instanceof Object[]) 218: return ((Object[]) array)[index]; 219: if (array instanceof boolean[]) 220: return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE; 221: if (array instanceof byte[]) 222: return new Byte(((byte[]) array)[index]); 223: if (array instanceof char[]) 224: return new Character(((char[]) array)[index]); 225: if (array instanceof short[]) 226: return new Short(((short[]) array)[index]); 227: if (array instanceof int[]) 228: return new Integer(((int[]) array)[index]); 229: if (array instanceof long[]) 230: return new Long(((long[]) array)[index]); 231: if (array instanceof float[]) 232: return new Float(((float[]) array)[index]); 233: if (array instanceof double[]) 234: return new Double(((double[]) array)[index]); 235: if (array == null) 236: throw new NullPointerException(); 237: throw new IllegalArgumentException(); 238: } 239: 240: /** 241: * Gets an element of a boolean array. 242: * 243: * @param array the array to access 244: * @param index the array index to access 245: * @return the boolean element at <code>array[index]</code> 246: * @throws IllegalArgumentException if <code>array</code> is not a boolean 247: * array 248: * @throws NullPointerException if <code>array</code> is null 249: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 250: * bounds 251: * @see #get(Object, int) 252: */ 253: public static boolean getBoolean(Object array, int index) 254: { 255: if (array instanceof boolean[]) 256: return ((boolean[]) array)[index]; 257: if (array == null) 258: throw new NullPointerException(); 259: throw new IllegalArgumentException(); 260: } 261: 262: /** 263: * Gets an element of a byte array. 264: * 265: * @param array the array to access 266: * @param index the array index to access 267: * @return the byte element at <code>array[index]</code> 268: * @throws IllegalArgumentException if <code>array</code> is not a byte 269: * array 270: * @throws NullPointerException if <code>array</code> is null 271: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 272: * bounds 273: * @see #get(Object, int) 274: */ 275: public static byte getByte(Object array, int index) 276: { 277: if (array instanceof byte[]) 278: return ((byte[]) array)[index]; 279: if (array == null) 280: throw new NullPointerException(); 281: throw new IllegalArgumentException(); 282: } 283: 284: /** 285: * Gets an element of a char array. 286: * 287: * @param array the array to access 288: * @param index the array index to access 289: * @return the char element at <code>array[index]</code> 290: * @throws IllegalArgumentException if <code>array</code> is not a char 291: * array 292: * @throws NullPointerException if <code>array</code> is null 293: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 294: * bounds 295: * @see #get(Object, int) 296: */ 297: public static char getChar(Object array, int index) 298: { 299: if (array instanceof char[]) 300: return ((char[]) array)[index]; 301: if (array == null) 302: throw new NullPointerException(); 303: throw new IllegalArgumentException(); 304: } 305: 306: /** 307: * Gets an element of a short array. 308: * 309: * @param array the array to access 310: * @param index the array index to access 311: * @return the short element at <code>array[index]</code> 312: * @throws IllegalArgumentException if <code>array</code> is not a byte 313: * or char array 314: * @throws NullPointerException if <code>array</code> is null 315: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 316: * bounds 317: * @see #get(Object, int) 318: */ 319: public static short getShort(Object array, int index) 320: { 321: if (array instanceof short[]) 322: return ((short[]) array)[index]; 323: return getByte(array, index); 324: } 325: 326: /** 327: * Gets an element of an int array. 328: * 329: * @param array the array to access 330: * @param index the array index to access 331: * @return the int element at <code>array[index]</code> 332: * @throws IllegalArgumentException if <code>array</code> is not a byte, 333: * char, short, or int array 334: * @throws NullPointerException if <code>array</code> is null 335: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 336: * bounds 337: * @see #get(Object, int) 338: */ 339: public static int getInt(Object array, int index) 340: { 341: if (array instanceof int[]) 342: return ((int[]) array)[index]; 343: if (array instanceof char[]) 344: return ((char[]) array)[index]; 345: return getShort(array, index); 346: } 347: 348: /** 349: * Gets an element of a long array. 350: * 351: * @param array the array to access 352: * @param index the array index to access 353: * @return the long element at <code>array[index]</code> 354: * @throws IllegalArgumentException if <code>array</code> is not a byte, 355: * char, short, int, or long array 356: * @throws NullPointerException if <code>array</code> is null 357: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 358: * bounds 359: * @see #get(Object, int) 360: */ 361: public static long getLong(Object array, int index) 362: { 363: if (array instanceof long[]) 364: return ((long[]) array)[index]; 365: return getInt(array, index); 366: } 367: 368: /** 369: * Gets an element of a float array. 370: * 371: * @param array the array to access 372: * @param index the array index to access 373: * @return the float element at <code>array[index]</code> 374: * @throws IllegalArgumentException if <code>array</code> is not a byte, 375: * char, short, int, long, or float array 376: * @throws NullPointerException if <code>array</code> is null 377: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 378: * bounds 379: * @see #get(Object, int) 380: */ 381: public static float getFloat(Object array, int index) 382: { 383: if (array instanceof float[]) 384: return ((float[]) array)[index]; 385: return getLong(array, index); 386: } 387: 388: /** 389: * Gets an element of a double array. 390: * 391: * @param array the array to access 392: * @param index the array index to access 393: * @return the double element at <code>array[index]</code> 394: * @throws IllegalArgumentException if <code>array</code> is not a byte, 395: * char, short, int, long, float, or double array 396: * @throws NullPointerException if <code>array</code> is null 397: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 398: * bounds 399: * @see #get(Object, int) 400: */ 401: public static double getDouble(Object array, int index) 402: { 403: if (array instanceof double[]) 404: return ((double[]) array)[index]; 405: return getFloat(array, index); 406: } 407: 408: /** 409: * Sets an element of an array. If the array is primitive, then the new 410: * value is unwrapped and widened. 411: * 412: * @param array the array to set a value of 413: * @param index the array index to set the value to 414: * @param value the value to set 415: * @throws IllegalArgumentException if <code>array</code> is not an array, 416: * or the array is primitive and unwrapping value fails, or the 417: * value is not assignable to the array component type 418: * @throws NullPointerException if array is null, or if array is primitive 419: * and value is null 420: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 421: * bounds 422: * @see #setBoolean(Object, int, boolean) 423: * @see #setByte(Object, int, byte) 424: * @see #setChar(Object, int, char) 425: * @see #setShort(Object, int, short) 426: * @see #setInt(Object, int, int) 427: * @see #setLong(Object, int, long) 428: * @see #setFloat(Object, int, float) 429: * @see #setDouble(Object, int, double) 430: */ 431: public static void set(Object array, int index, Object value) 432: { 433: if (array instanceof Object[]) 434: { 435: // Too bad the API won't let us throw the easier ArrayStoreException! 436: if (value != null 437: && ! array.getClass().getComponentType().isInstance(value)) 438: throw new IllegalArgumentException(); 439: ((Object[]) array)[index] = value; 440: } 441: else if (value instanceof Byte) 442: setByte(array, index, ((Byte) value).byteValue()); 443: else if (value instanceof Short) 444: setShort(array, index, ((Short) value).shortValue()); 445: else if (value instanceof Integer) 446: setInt(array, index, ((Integer) value).intValue()); 447: else if (value instanceof Long) 448: setLong(array, index, ((Long) value).longValue()); 449: else if (value instanceof Float) 450: setFloat(array, index, ((Float) value).floatValue()); 451: else if (value instanceof Double) 452: setDouble(array, index, ((Double) value).doubleValue()); 453: else if (value instanceof Character) 454: setChar(array, index, ((Character) value).charValue()); 455: else if (value instanceof Boolean) 456: setBoolean(array, index, ((Boolean) value).booleanValue()); 457: else if (array == null) 458: throw new NullPointerException(); 459: else 460: throw new IllegalArgumentException(); 461: } 462: 463: /** 464: * Sets an element of a boolean array. 465: * 466: * @param array the array to set a value of 467: * @param index the array index to set the value to 468: * @param value the value to set 469: * @throws IllegalArgumentException if <code>array</code> is not a boolean 470: * array 471: * @throws NullPointerException if <code>array</code> is null 472: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 473: * bounds 474: * @see #set(Object, int, Object) 475: */ 476: public static void setBoolean(Object array, int index, boolean value) 477: { 478: if (array instanceof boolean[]) 479: ((boolean[]) array)[index] = value; 480: else if (array == null) 481: throw new NullPointerException(); 482: else 483: throw new IllegalArgumentException(); 484: } 485: 486: /** 487: * Sets an element of a byte array. 488: * 489: * @param array the array to set a value of 490: * @param index the array index to set the value to 491: * @param value the value to set 492: * @throws IllegalArgumentException if <code>array</code> is not a byte, 493: * short, int, long, float, or double array 494: * @throws NullPointerException if <code>array</code> is null 495: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 496: * bounds 497: * @see #set(Object, int, Object) 498: */ 499: public static void setByte(Object array, int index, byte value) 500: { 501: if (array instanceof byte[]) 502: ((byte[]) array)[index] = value; 503: else 504: setShort(array, index, value); 505: } 506: 507: /** 508: * Sets an element of a char array. 509: * 510: * @param array the array to set a value of 511: * @param index the array index to set the value to 512: * @param value the value to set 513: * @throws IllegalArgumentException if <code>array</code> is not a char, 514: * int, long, float, or double array 515: * @throws NullPointerException if <code>array</code> is null 516: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 517: * bounds 518: * @see #set(Object, int, Object) 519: */ 520: public static void setChar(Object array, int index, char value) 521: { 522: if (array instanceof char[]) 523: ((char[]) array)[index] = value; 524: else 525: setInt(array, index, value); 526: } 527: 528: /** 529: * Sets an element of a short array. 530: * 531: * @param array the array to set a value of 532: * @param index the array index to set the value to 533: * @param value the value to set 534: * @throws IllegalArgumentException if <code>array</code> is not a short, 535: * int, long, float, or double array 536: * @throws NullPointerException if <code>array</code> is null 537: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 538: * bounds 539: * @see #set(Object, int, Object) 540: */ 541: public static void setShort(Object array, int index, short value) 542: { 543: if (array instanceof short[]) 544: ((short[]) array)[index] = value; 545: else 546: setInt(array, index, value); 547: } 548: 549: /** 550: * Sets an element of an int array. 551: * 552: * @param array the array to set a value of 553: * @param index the array index to set the value to 554: * @param value the value to set 555: * @throws IllegalArgumentException if <code>array</code> is not an int, 556: * long, float, or double array 557: * @throws NullPointerException if <code>array</code> is null 558: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 559: * bounds 560: * @see #set(Object, int, Object) 561: */ 562: public static void setInt(Object array, int index, int value) 563: { 564: if (array instanceof int[]) 565: ((int[]) array)[index] = value; 566: else 567: setLong(array, index, value); 568: } 569: 570: /** 571: * Sets an element of a long array. 572: * 573: * @param array the array to set a value of 574: * @param index the array index to set the value to 575: * @param value the value to set 576: * @throws IllegalArgumentException if <code>array</code> is not a long, 577: * float, or double array 578: * @throws NullPointerException if <code>array</code> is null 579: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 580: * bounds 581: * @see #set(Object, int, Object) 582: */ 583: public static void setLong(Object array, int index, long value) 584: { 585: if (array instanceof long[]) 586: ((long[]) array)[index] = value; 587: else 588: setFloat(array, index, value); 589: } 590: 591: /** 592: * Sets an element of a float array. 593: * 594: * @param array the array to set a value of 595: * @param index the array index to set the value to 596: * @param value the value to set 597: * @throws IllegalArgumentException if <code>array</code> is not a float 598: * or double array 599: * @throws NullPointerException if <code>array</code> is null 600: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 601: * bounds 602: * @see #set(Object, int, Object) 603: */ 604: public static void setFloat(Object array, int index, float value) 605: { 606: if (array instanceof float[]) 607: ((float[]) array)[index] = value; 608: else 609: setDouble(array, index, value); 610: } 611: 612: /** 613: * Sets an element of a double array. 614: * 615: * @param array the array to set a value of 616: * @param index the array index to set the value to 617: * @param value the value to set 618: * @throws IllegalArgumentException if <code>array</code> is not a double 619: * array 620: * @throws NullPointerException if <code>array</code> is null 621: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 622: * bounds 623: * @see #set(Object, int, Object) 624: */ 625: public static void setDouble(Object array, int index, double value) 626: { 627: if (array instanceof double[]) 628: ((double[]) array)[index] = value; 629: else if (array == null) 630: throw new NullPointerException(); 631: else 632: throw new IllegalArgumentException(); 633: } 634: 635: /** 636: * Dynamically and recursively create a multi-dimensioned array of objects. 637: * 638: * @param type guaranteed to be a valid object type 639: * @param dimensions the dimensions of the array 640: * @param index index of the current dimension to build 641: * @return the new multi-dimensioned array 642: * @throws NegativeArraySizeException if any entry of dimensions is negative 643: * @throws OutOfMemoryError if memory allocation fails 644: */ 645: // This would be faster if implemented natively, using the multianewarray 646: // bytecode instead of this recursive call 647: private static Object createMultiArray(Class type, int[] dimensions, 648: int index) 649: { 650: if (index == 0) 651: return newInstance(type, dimensions[0]); 652: 653: Object toAdd = createMultiArray(type, dimensions, index - 1); 654: Class thisType = toAdd.getClass(); 655: Object[] retval 656: = (Object[]) createObjectArray(thisType, dimensions[index]); 657: if (dimensions[index] > 0) 658: retval[0] = toAdd; 659: int i = dimensions[index]; 660: while (--i > 0) 661: retval[i] = createMultiArray(type, dimensions, index - 1); 662: return retval; 663: } 664: 665: /** 666: * Dynamically create an array of objects. 667: * 668: * @param type guaranteed to be a valid object type 669: * @param dim the length of the array 670: * @return the new array 671: * @throws NegativeArraySizeException if dim is negative 672: * @throws OutOfMemoryError if memory allocation fails 673: */ 674: private static native Object createObjectArray(Class type, int dim); 675: }
GNU Classpath (0.20) |