GNU Classpath (0.97.2) | |
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, 0); 151: } 152: 153: /** 154: * Gets the array length. 155: * @param array the array 156: * @return the length of the array 157: * @throws IllegalArgumentException if <code>array</code> is not an array 158: * @throws NullPointerException if <code>array</code> is null 159: */ 160: public static int getLength(Object array) 161: { 162: if (array instanceof Object[]) 163: return ((Object[]) array).length; 164: if (array instanceof boolean[]) 165: return ((boolean[]) array).length; 166: if (array instanceof byte[]) 167: return ((byte[]) array). length; 168: if (array instanceof char[]) 169: return ((char[]) array).length; 170: if (array instanceof short[]) 171: return ((short[]) array).length; 172: if (array instanceof int[]) 173: return ((int[]) array).length; 174: if (array instanceof long[]) 175: return ((long[]) array).length; 176: if (array instanceof float[]) 177: return ((float[]) array).length; 178: if (array instanceof double[]) 179: return ((double[]) array).length; 180: if (array == null) 181: throw new NullPointerException(); 182: throw new IllegalArgumentException(); 183: } 184: 185: /** 186: * Gets an element of an array. Primitive elements will be wrapped in 187: * the corresponding class type. 188: * 189: * @param array the array to access 190: * @param index the array index to access 191: * @return the element at <code>array[index]</code> 192: * @throws IllegalArgumentException if <code>array</code> is not an array 193: * @throws NullPointerException if <code>array</code> is null 194: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 195: * bounds 196: * @see #getBoolean(Object, int) 197: * @see #getByte(Object, int) 198: * @see #getChar(Object, int) 199: * @see #getShort(Object, int) 200: * @see #getInt(Object, int) 201: * @see #getLong(Object, int) 202: * @see #getFloat(Object, int) 203: * @see #getDouble(Object, int) 204: */ 205: public static Object get(Object array, int index) 206: { 207: if (array instanceof Object[]) 208: return ((Object[]) array)[index]; 209: if (array instanceof boolean[]) 210: return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE; 211: if (array instanceof byte[]) 212: return Byte.valueOf(((byte[]) array)[index]); 213: if (array instanceof char[]) 214: return Character.valueOf(((char[]) array)[index]); 215: if (array instanceof short[]) 216: return Short.valueOf(((short[]) array)[index]); 217: if (array instanceof int[]) 218: return Integer.valueOf(((int[]) array)[index]); 219: if (array instanceof long[]) 220: return Long.valueOf(((long[]) array)[index]); 221: if (array instanceof float[]) 222: return Float.valueOf(((float[]) array)[index]); 223: if (array instanceof double[]) 224: return Double.valueOf(((double[]) array)[index]); 225: if (array == null) 226: throw new NullPointerException(); 227: throw new IllegalArgumentException(); 228: } 229: 230: /** 231: * Gets an element of a boolean array. 232: * 233: * @param array the array to access 234: * @param index the array index to access 235: * @return the boolean element at <code>array[index]</code> 236: * @throws IllegalArgumentException if <code>array</code> is not a boolean 237: * array 238: * @throws NullPointerException if <code>array</code> is null 239: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 240: * bounds 241: * @see #get(Object, int) 242: */ 243: public static boolean getBoolean(Object array, int index) 244: { 245: if (array instanceof boolean[]) 246: return ((boolean[]) array)[index]; 247: if (array == null) 248: throw new NullPointerException(); 249: throw new IllegalArgumentException(); 250: } 251: 252: /** 253: * Gets an element of a byte array. 254: * 255: * @param array the array to access 256: * @param index the array index to access 257: * @return the byte element at <code>array[index]</code> 258: * @throws IllegalArgumentException if <code>array</code> is not a byte 259: * array 260: * @throws NullPointerException if <code>array</code> is null 261: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 262: * bounds 263: * @see #get(Object, int) 264: */ 265: public static byte getByte(Object array, int index) 266: { 267: if (array instanceof byte[]) 268: return ((byte[]) array)[index]; 269: if (array == null) 270: throw new NullPointerException(); 271: throw new IllegalArgumentException(); 272: } 273: 274: /** 275: * Gets an element of a char array. 276: * 277: * @param array the array to access 278: * @param index the array index to access 279: * @return the char element at <code>array[index]</code> 280: * @throws IllegalArgumentException if <code>array</code> is not a char 281: * array 282: * @throws NullPointerException if <code>array</code> is null 283: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 284: * bounds 285: * @see #get(Object, int) 286: */ 287: public static char getChar(Object array, int index) 288: { 289: if (array instanceof char[]) 290: return ((char[]) array)[index]; 291: if (array == null) 292: throw new NullPointerException(); 293: throw new IllegalArgumentException(); 294: } 295: 296: /** 297: * Gets an element of a short array. 298: * 299: * @param array the array to access 300: * @param index the array index to access 301: * @return the short element at <code>array[index]</code> 302: * @throws IllegalArgumentException if <code>array</code> is not a byte 303: * or char array 304: * @throws NullPointerException if <code>array</code> is null 305: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 306: * bounds 307: * @see #get(Object, int) 308: */ 309: public static short getShort(Object array, int index) 310: { 311: if (array instanceof short[]) 312: return ((short[]) array)[index]; 313: return getByte(array, index); 314: } 315: 316: /** 317: * Gets an element of an int array. 318: * 319: * @param array the array to access 320: * @param index the array index to access 321: * @return the int element at <code>array[index]</code> 322: * @throws IllegalArgumentException if <code>array</code> is not a byte, 323: * char, short, or int array 324: * @throws NullPointerException if <code>array</code> is null 325: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 326: * bounds 327: * @see #get(Object, int) 328: */ 329: public static int getInt(Object array, int index) 330: { 331: if (array instanceof int[]) 332: return ((int[]) array)[index]; 333: if (array instanceof char[]) 334: return ((char[]) array)[index]; 335: return getShort(array, index); 336: } 337: 338: /** 339: * Gets an element of a long array. 340: * 341: * @param array the array to access 342: * @param index the array index to access 343: * @return the long element at <code>array[index]</code> 344: * @throws IllegalArgumentException if <code>array</code> is not a byte, 345: * char, short, int, or long array 346: * @throws NullPointerException if <code>array</code> is null 347: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 348: * bounds 349: * @see #get(Object, int) 350: */ 351: public static long getLong(Object array, int index) 352: { 353: if (array instanceof long[]) 354: return ((long[]) array)[index]; 355: return getInt(array, index); 356: } 357: 358: /** 359: * Gets an element of a float array. 360: * 361: * @param array the array to access 362: * @param index the array index to access 363: * @return the float element at <code>array[index]</code> 364: * @throws IllegalArgumentException if <code>array</code> is not a byte, 365: * char, short, int, long, or float array 366: * @throws NullPointerException if <code>array</code> is null 367: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 368: * bounds 369: * @see #get(Object, int) 370: */ 371: public static float getFloat(Object array, int index) 372: { 373: if (array instanceof float[]) 374: return ((float[]) array)[index]; 375: return getLong(array, index); 376: } 377: 378: /** 379: * Gets an element of a double array. 380: * 381: * @param array the array to access 382: * @param index the array index to access 383: * @return the double element at <code>array[index]</code> 384: * @throws IllegalArgumentException if <code>array</code> is not a byte, 385: * char, short, int, long, float, or double array 386: * @throws NullPointerException if <code>array</code> is null 387: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 388: * bounds 389: * @see #get(Object, int) 390: */ 391: public static double getDouble(Object array, int index) 392: { 393: if (array instanceof double[]) 394: return ((double[]) array)[index]; 395: return getFloat(array, index); 396: } 397: 398: /** 399: * Sets an element of an array. If the array is primitive, then the new 400: * value is unwrapped and widened. 401: * 402: * @param array the array to set a value of 403: * @param index the array index to set the value to 404: * @param value the value to set 405: * @throws IllegalArgumentException if <code>array</code> is not an array, 406: * or the array is primitive and unwrapping value fails, or the 407: * value is not assignable to the array component type 408: * @throws NullPointerException if array is null, or if array is primitive 409: * and value is null 410: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 411: * bounds 412: * @see #setBoolean(Object, int, boolean) 413: * @see #setByte(Object, int, byte) 414: * @see #setChar(Object, int, char) 415: * @see #setShort(Object, int, short) 416: * @see #setInt(Object, int, int) 417: * @see #setLong(Object, int, long) 418: * @see #setFloat(Object, int, float) 419: * @see #setDouble(Object, int, double) 420: */ 421: public static void set(Object array, int index, Object value) 422: { 423: if (array instanceof Object[]) 424: { 425: // Too bad the API won't let us throw the easier ArrayStoreException! 426: if (value != null 427: && ! array.getClass().getComponentType().isInstance(value)) 428: throw new IllegalArgumentException(); 429: ((Object[]) array)[index] = value; 430: } 431: else if (value instanceof Byte) 432: setByte(array, index, ((Byte) value).byteValue()); 433: else if (value instanceof Short) 434: setShort(array, index, ((Short) value).shortValue()); 435: else if (value instanceof Integer) 436: setInt(array, index, ((Integer) value).intValue()); 437: else if (value instanceof Long) 438: setLong(array, index, ((Long) value).longValue()); 439: else if (value instanceof Float) 440: setFloat(array, index, ((Float) value).floatValue()); 441: else if (value instanceof Double) 442: setDouble(array, index, ((Double) value).doubleValue()); 443: else if (value instanceof Character) 444: setChar(array, index, ((Character) value).charValue()); 445: else if (value instanceof Boolean) 446: setBoolean(array, index, ((Boolean) value).booleanValue()); 447: else if (array == null) 448: throw new NullPointerException(); 449: else 450: throw new IllegalArgumentException(); 451: } 452: 453: /** 454: * Sets an element of a boolean array. 455: * 456: * @param array the array to set a value of 457: * @param index the array index to set the value to 458: * @param value the value to set 459: * @throws IllegalArgumentException if <code>array</code> is not a boolean 460: * array 461: * @throws NullPointerException if <code>array</code> is null 462: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 463: * bounds 464: * @see #set(Object, int, Object) 465: */ 466: public static void setBoolean(Object array, int index, boolean value) 467: { 468: if (array instanceof boolean[]) 469: ((boolean[]) array)[index] = value; 470: else if (array == null) 471: throw new NullPointerException(); 472: else 473: throw new IllegalArgumentException(); 474: } 475: 476: /** 477: * Sets an element of a byte array. 478: * 479: * @param array the array to set a value of 480: * @param index the array index to set the value to 481: * @param value the value to set 482: * @throws IllegalArgumentException if <code>array</code> is not a byte, 483: * short, int, long, float, or double array 484: * @throws NullPointerException if <code>array</code> is null 485: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 486: * bounds 487: * @see #set(Object, int, Object) 488: */ 489: public static void setByte(Object array, int index, byte value) 490: { 491: if (array instanceof byte[]) 492: ((byte[]) array)[index] = value; 493: else 494: setShort(array, index, value); 495: } 496: 497: /** 498: * Sets an element of a char array. 499: * 500: * @param array the array to set a value of 501: * @param index the array index to set the value to 502: * @param value the value to set 503: * @throws IllegalArgumentException if <code>array</code> is not a char, 504: * int, long, float, or double array 505: * @throws NullPointerException if <code>array</code> is null 506: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 507: * bounds 508: * @see #set(Object, int, Object) 509: */ 510: public static void setChar(Object array, int index, char value) 511: { 512: if (array instanceof char[]) 513: ((char[]) array)[index] = value; 514: else 515: setInt(array, index, value); 516: } 517: 518: /** 519: * Sets an element of a short array. 520: * 521: * @param array the array to set a value of 522: * @param index the array index to set the value to 523: * @param value the value to set 524: * @throws IllegalArgumentException if <code>array</code> is not a short, 525: * int, long, float, or double array 526: * @throws NullPointerException if <code>array</code> is null 527: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 528: * bounds 529: * @see #set(Object, int, Object) 530: */ 531: public static void setShort(Object array, int index, short value) 532: { 533: if (array instanceof short[]) 534: ((short[]) array)[index] = value; 535: else 536: setInt(array, index, value); 537: } 538: 539: /** 540: * Sets an element of an int array. 541: * 542: * @param array the array to set a value of 543: * @param index the array index to set the value to 544: * @param value the value to set 545: * @throws IllegalArgumentException if <code>array</code> is not an int, 546: * long, float, or double array 547: * @throws NullPointerException if <code>array</code> is null 548: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 549: * bounds 550: * @see #set(Object, int, Object) 551: */ 552: public static void setInt(Object array, int index, int value) 553: { 554: if (array instanceof int[]) 555: ((int[]) array)[index] = value; 556: else 557: setLong(array, index, value); 558: } 559: 560: /** 561: * Sets an element of a long array. 562: * 563: * @param array the array to set a value of 564: * @param index the array index to set the value to 565: * @param value the value to set 566: * @throws IllegalArgumentException if <code>array</code> is not a long, 567: * float, or double array 568: * @throws NullPointerException if <code>array</code> is null 569: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 570: * bounds 571: * @see #set(Object, int, Object) 572: */ 573: public static void setLong(Object array, int index, long value) 574: { 575: if (array instanceof long[]) 576: ((long[]) array)[index] = value; 577: else 578: setFloat(array, index, value); 579: } 580: 581: /** 582: * Sets an element of a float array. 583: * 584: * @param array the array to set a value of 585: * @param index the array index to set the value to 586: * @param value the value to set 587: * @throws IllegalArgumentException if <code>array</code> is not a float 588: * or double array 589: * @throws NullPointerException if <code>array</code> is null 590: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 591: * bounds 592: * @see #set(Object, int, Object) 593: */ 594: public static void setFloat(Object array, int index, float value) 595: { 596: if (array instanceof float[]) 597: ((float[]) array)[index] = value; 598: else 599: setDouble(array, index, value); 600: } 601: 602: /** 603: * Sets an element of a double array. 604: * 605: * @param array the array to set a value of 606: * @param index the array index to set the value to 607: * @param value the value to set 608: * @throws IllegalArgumentException if <code>array</code> is not a double 609: * array 610: * @throws NullPointerException if <code>array</code> is null 611: * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 612: * bounds 613: * @see #set(Object, int, Object) 614: */ 615: public static void setDouble(Object array, int index, double value) 616: { 617: if (array instanceof double[]) 618: ((double[]) array)[index] = value; 619: else if (array == null) 620: throw new NullPointerException(); 621: else 622: throw new IllegalArgumentException(); 623: } 624: 625: /** 626: * Dynamically and recursively create a multi-dimensioned array of objects. 627: * 628: * @param type guaranteed to be a valid object type 629: * @param dimensions the dimensions of the array 630: * @param index index of the current dimension to build 631: * @return the new multi-dimensioned array 632: * @throws NegativeArraySizeException if any entry of dimensions is negative 633: * @throws OutOfMemoryError if memory allocation fails 634: */ 635: // This would be faster if implemented natively, using the multianewarray 636: // bytecode instead of this recursive call 637: private static Object createMultiArray(Class type, int[] dimensions, 638: int index) 639: { 640: if (index == dimensions.length - 1) 641: return newInstance(type, dimensions[index]); 642: 643: Object toAdd = createMultiArray(type, dimensions, index + 1); 644: Class thisType = toAdd.getClass(); 645: Object[] retval 646: = (Object[]) VMArray.createObjectArray(thisType, dimensions[index]); 647: if (dimensions[index] > 0) 648: retval[0] = toAdd; 649: int i = dimensions[index]; 650: while (--i > 0) 651: retval[i] = createMultiArray(type, dimensions, index + 1); 652: return retval; 653: } 654: 655: }
GNU Classpath (0.97.2) |