1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /* 18 * Copyright (C) 2008 The Android Open Source Project 19 * 20 * Licensed under the Apache License, Version 2.0 (the "License"); 21 * you may not use this file except in compliance with the License. 22 * You may obtain a copy of the License at 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, 28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 * See the License for the specific language governing permissions and 30 * limitations under the License. 31 */ 32 33 package java.lang.reflect; 34 35 /** 36 * Provides static methods to create and access arrays dynamically. 37 */ 38 public final class Array { 39 private Array() { 40 } 41 42 private static IllegalArgumentException notAnArray(Object o) { 43 throw new IllegalArgumentException("Not an array: " + o.getClass()); 44 } 45 46 private static IllegalArgumentException incompatibleType(Object o) { 47 throw new IllegalArgumentException("Array has incompatible type: " + o.getClass()); 48 } 49 50 private static RuntimeException badArray(Object array) { 51 if (array == null) { 52 throw new NullPointerException("array == null"); 53 } else if (!array.getClass().isArray()) { 54 throw notAnArray(array); 55 } else { 56 throw incompatibleType(array); 57 } 58 } 59 60 /** 61 * Returns the element of the array at the specified index. Equivalent to {@code array[index]}. 62 * If the array component is a primitive type, the result is automatically boxed. 63 * 64 * @throws NullPointerException if {@code array == null} 65 * @throws IllegalArgumentException 66 * if {@code array} is not an array 67 * @throws ArrayIndexOutOfBoundsException 68 * if {@code index < 0 || index >= array.length} 69 */ 70 public static Object get(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 71 if (array instanceof Object[]) { 72 return ((Object[]) array)[index]; 73 } 74 if (array instanceof boolean[]) { 75 return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE; 76 } 77 if (array instanceof byte[]) { 78 return Byte.valueOf(((byte[]) array)[index]); 79 } 80 if (array instanceof char[]) { 81 return Character.valueOf(((char[]) array)[index]); 82 } 83 if (array instanceof short[]) { 84 return Short.valueOf(((short[]) array)[index]); 85 } 86 if (array instanceof int[]) { 87 return Integer.valueOf(((int[]) array)[index]); 88 } 89 if (array instanceof long[]) { 90 return Long.valueOf(((long[]) array)[index]); 91 } 92 if (array instanceof float[]) { 93 return new Float(((float[]) array)[index]); 94 } 95 if (array instanceof double[]) { 96 return new Double(((double[]) array)[index]); 97 } 98 if (array == null) { 99 throw new NullPointerException("array == null"); 100 } 101 throw notAnArray(array); 102 } 103 104 /** 105 * Returns the boolean at the given index in the given boolean array. 106 * 107 * @throws NullPointerException if {@code array == null} 108 * @throws IllegalArgumentException 109 * if {@code array} is not an array or the element at the 110 * index position can not be converted to the return type 111 * @throws ArrayIndexOutOfBoundsException 112 * if {@code index < 0 || index >= array.length} 113 */ 114 public static boolean getBoolean(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 115 if (array instanceof boolean[]) { 116 return ((boolean[]) array)[index]; 117 } 118 throw badArray(array); 119 } 120 121 /** 122 * Returns the byte at the given index in the given byte array. 123 * 124 * @throws NullPointerException if {@code array == null} 125 * @throws IllegalArgumentException 126 * if {@code array} is not an array or the element at the 127 * index position can not be converted to the return type 128 * @throws ArrayIndexOutOfBoundsException 129 * if {@code index < 0 || index >= array.length} 130 */ 131 public static byte getByte(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 132 if (array instanceof byte[]) { 133 return ((byte[]) array)[index]; 134 } 135 throw badArray(array); 136 } 137 138 /** 139 * Returns the char at the given index in the given char array. 140 * 141 * @throws NullPointerException if {@code array == null} 142 * @throws IllegalArgumentException 143 * if {@code array} is not an array or the element at the 144 * index position can not be converted to the return type 145 * @throws ArrayIndexOutOfBoundsException 146 * if {@code index < 0 || index >= array.length} 147 */ 148 public static char getChar(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 149 if (array instanceof char[]) { 150 return ((char[]) array)[index]; 151 } 152 throw badArray(array); 153 } 154 155 /** 156 * Returns the double at the given index in the given array. 157 * Applies to byte, char, float, double, int, long, and short arrays. 158 * 159 * @throws NullPointerException if {@code array == null} 160 * @throws IllegalArgumentException 161 * if {@code array} is not an array or the element at the 162 * index position can not be converted to the return type 163 * @throws ArrayIndexOutOfBoundsException 164 * if {@code index < 0 || index >= array.length} 165 */ 166 public static double getDouble(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 167 if (array instanceof double[]) { 168 return ((double[]) array)[index]; 169 } else if (array instanceof byte[]) { 170 return ((byte[]) array)[index]; 171 } else if (array instanceof char[]) { 172 return ((char[]) array)[index]; 173 } else if (array instanceof float[]) { 174 return ((float[]) array)[index]; 175 } else if (array instanceof int[]) { 176 return ((int[]) array)[index]; 177 } else if (array instanceof long[]) { 178 return ((long[]) array)[index]; 179 } else if (array instanceof short[]) { 180 return ((short[]) array)[index]; 181 } 182 throw badArray(array); 183 } 184 185 /** 186 * Returns the float at the given index in the given array. 187 * Applies to byte, char, float, int, long, and short arrays. 188 * 189 * @throws NullPointerException if {@code array == null} 190 * @throws IllegalArgumentException 191 * if {@code array} is not an array or the element at the 192 * index position can not be converted to the return type 193 * @throws ArrayIndexOutOfBoundsException 194 * if {@code index < 0 || index >= array.length} 195 */ 196 public static float getFloat(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 197 if (array instanceof float[]) { 198 return ((float[]) array)[index]; 199 } else if (array instanceof byte[]) { 200 return ((byte[]) array)[index]; 201 } else if (array instanceof char[]) { 202 return ((char[]) array)[index]; 203 } else if (array instanceof int[]) { 204 return ((int[]) array)[index]; 205 } else if (array instanceof long[]) { 206 return ((long[]) array)[index]; 207 } else if (array instanceof short[]) { 208 return ((short[]) array)[index]; 209 } 210 throw badArray(array); 211 } 212 213 /** 214 * Returns the int at the given index in the given array. 215 * Applies to byte, char, int, and short arrays. 216 * 217 * @throws NullPointerException if {@code array == null} 218 * @throws IllegalArgumentException 219 * if {@code array} is not an array or the element at the 220 * index position can not be converted to the return type 221 * @throws ArrayIndexOutOfBoundsException 222 * if {@code index < 0 || index >= array.length} 223 */ 224 public static int getInt(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 225 if (array instanceof int[]) { 226 return ((int[]) array)[index]; 227 } else if (array instanceof byte[]) { 228 return ((byte[]) array)[index]; 229 } else if (array instanceof char[]) { 230 return ((char[]) array)[index]; 231 } else if (array instanceof short[]) { 232 return ((short[]) array)[index]; 233 } 234 throw badArray(array); 235 } 236 237 /** 238 * Returns the length of the array. Equivalent to {@code array.length}. 239 * 240 * @throws NullPointerException if {@code array == null} 241 * @throws IllegalArgumentException 242 * if {@code array} is not an array 243 */ 244 public static int getLength(Object array) { 245 if (array instanceof Object[]) { 246 return ((Object[]) array).length; 247 } else if (array instanceof boolean[]) { 248 return ((boolean[]) array).length; 249 } else if (array instanceof byte[]) { 250 return ((byte[]) array).length; 251 } else if (array instanceof char[]) { 252 return ((char[]) array).length; 253 } else if (array instanceof double[]) { 254 return ((double[]) array).length; 255 } else if (array instanceof float[]) { 256 return ((float[]) array).length; 257 } else if (array instanceof int[]) { 258 return ((int[]) array).length; 259 } else if (array instanceof long[]) { 260 return ((long[]) array).length; 261 } else if (array instanceof short[]) { 262 return ((short[]) array).length; 263 } 264 throw badArray(array); 265 } 266 267 /** 268 * Returns the long at the given index in the given array. 269 * Applies to byte, char, int, long, and short arrays. 270 * 271 * @throws NullPointerException if {@code array == null} 272 * @throws IllegalArgumentException 273 * if {@code array} is not an array or the element at the 274 * index position can not be converted to the return type 275 * @throws ArrayIndexOutOfBoundsException 276 * if {@code index < 0 || index >= array.length} 277 */ 278 public static long getLong(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 279 if (array instanceof long[]) { 280 return ((long[]) array)[index]; 281 } else if (array instanceof byte[]) { 282 return ((byte[]) array)[index]; 283 } else if (array instanceof char[]) { 284 return ((char[]) array)[index]; 285 } else if (array instanceof int[]) { 286 return ((int[]) array)[index]; 287 } else if (array instanceof short[]) { 288 return ((short[]) array)[index]; 289 } 290 throw badArray(array); 291 } 292 293 /** 294 * Returns the short at the given index in the given array. 295 * Applies to byte and short arrays. 296 * 297 * @throws NullPointerException if {@code array == null} 298 * @throws IllegalArgumentException 299 * if {@code array} is not an array or the element at the 300 * index position can not be converted to the return type 301 * @throws ArrayIndexOutOfBoundsException 302 * if {@code index < 0 || index >= array.length} 303 */ 304 public static short getShort(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 305 if (array instanceof short[]) { 306 return ((short[]) array)[index]; 307 } else if (array instanceof byte[]) { 308 return ((byte[]) array)[index]; 309 } 310 throw badArray(array); 311 } 312 313 /** 314 * Returns a new multidimensional array of the specified component type and 315 * dimensions. Equivalent to {@code new componentType[d0][d1]...[dn]} for a 316 * dimensions array of { d0, d1, ... , dn }. 317 * 318 * @throws NullPointerException if {@code array == null} 319 * @throws NegativeArraySizeException 320 * if any of the dimensions are negative 321 * @throws IllegalArgumentException 322 * if the array of dimensions is of size zero, or exceeds the 323 * limit of the number of dimension for an array (currently 255) 324 */ 325 public static Object newInstance(Class<?> componentType, int... dimensions) throws NegativeArraySizeException, IllegalArgumentException { 326 if (dimensions.length <= 0 || dimensions.length > 255) { 327 throw new IllegalArgumentException("Bad number of dimensions: " + dimensions.length); 328 } 329 if (componentType == void.class) { 330 throw new IllegalArgumentException("Can't allocate an array of void"); 331 } 332 if (componentType == null) { 333 throw new NullPointerException("componentType == null"); 334 } 335 return createMultiArray(componentType, dimensions); 336 } 337 338 /* 339 * Create a multi-dimensional array of objects with the specified type. 340 */ 341 private static native Object createMultiArray(Class<?> componentType, int[] dimensions) throws NegativeArraySizeException; 342 343 /** 344 * Returns a new array of the specified component type and length. 345 * Equivalent to {@code new componentType[size]}. 346 * 347 * @throws NullPointerException 348 * if the component type is null 349 * @throws NegativeArraySizeException 350 * if {@code size < 0} 351 */ 352 public static Object newInstance(Class<?> componentType, int size) throws NegativeArraySizeException { 353 if (!componentType.isPrimitive()) { 354 return createObjectArray(componentType, size); 355 } else if (componentType == boolean.class) { 356 return new boolean[size]; 357 } else if (componentType == byte.class) { 358 return new byte[size]; 359 } else if (componentType == char.class) { 360 return new char[size]; 361 } else if (componentType == short.class) { 362 return new short[size]; 363 } else if (componentType == int.class) { 364 return new int[size]; 365 } else if (componentType == long.class) { 366 return new long[size]; 367 } else if (componentType == float.class) { 368 return new float[size]; 369 } else if (componentType == double.class) { 370 return new double[size]; 371 } else if (componentType == void.class) { 372 throw new IllegalArgumentException("Can't allocate an array of void"); 373 } 374 throw new AssertionError(); 375 } 376 377 /* 378 * Create a one-dimensional array of objects with the specified type. 379 */ 380 private static native Object createObjectArray(Class<?> componentType, int length) throws NegativeArraySizeException; 381 382 /** 383 * Sets the element of the array at the specified index to the value. 384 * Equivalent to {@code array[index] = value}. If the array 385 * component is a primitive type, the value is automatically unboxed. 386 * 387 * @throws NullPointerException if {@code array == null} 388 * @throws IllegalArgumentException 389 * if {@code array} is not an array or the value cannot be 390 * converted to the array type by a widening conversion 391 * @throws ArrayIndexOutOfBoundsException 392 * if {@code index < 0 || index >= array.length} 393 */ 394 public static void set(Object array, int index, Object value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 395 if (!array.getClass().isArray()) { 396 throw notAnArray(array); 397 } 398 399 if (array instanceof Object[]) { 400 if (value != null && !array.getClass().getComponentType().isInstance(value)) { 401 throw incompatibleType(array); 402 } 403 ((Object[]) array)[index] = value; 404 } else { 405 if (value == null) { 406 throw new IllegalArgumentException("Primitive array can't take null values."); 407 } 408 if (value instanceof Boolean) { 409 setBoolean(array, index, ((Boolean) value).booleanValue()); 410 } else if (value instanceof Byte) { 411 setByte(array, index, ((Byte) value).byteValue()); 412 } else if (value instanceof Character) { 413 setChar(array, index, ((Character) value).charValue()); 414 } else if (value instanceof Short) { 415 setShort(array, index, ((Short) value).shortValue()); 416 } else if (value instanceof Integer) { 417 setInt(array, index, ((Integer) value).intValue()); 418 } else if (value instanceof Long) { 419 setLong(array, index, ((Long) value).longValue()); 420 } else if (value instanceof Float) { 421 setFloat(array, index, ((Float) value).floatValue()); 422 } else if (value instanceof Double) { 423 setDouble(array, index, ((Double) value).doubleValue()); 424 } 425 } 426 } 427 428 /** 429 * Sets {@code array[index] = value}. Applies to boolean arrays. 430 * 431 * @throws NullPointerException if {@code array == null} 432 * @throws IllegalArgumentException 433 * if the {@code array} is not an array or the value cannot be 434 * converted to the array type by a widening conversion 435 * @throws ArrayIndexOutOfBoundsException 436 * if {@code index < 0 || index >= array.length} 437 */ 438 public static void setBoolean(Object array, int index, boolean value) { 439 if (array instanceof boolean[]) { 440 ((boolean[]) array)[index] = value; 441 } else { 442 throw badArray(array); 443 } 444 } 445 446 /** 447 * Sets {@code array[index] = value}. Applies to byte, double, float, int, long, and short arrays. 448 * 449 * @throws NullPointerException if {@code array == null} 450 * @throws IllegalArgumentException 451 * if the {@code array} is not an array or the value cannot be 452 * converted to the array type by a widening conversion 453 * @throws ArrayIndexOutOfBoundsException 454 * if {@code index < 0 || index >= array.length} 455 */ 456 public static void setByte(Object array, int index, byte value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 457 if (array instanceof byte[]) { 458 ((byte[]) array)[index] = value; 459 } else if (array instanceof double[]) { 460 ((double[]) array)[index] = value; 461 } else if (array instanceof float[]) { 462 ((float[]) array)[index] = value; 463 } else if (array instanceof int[]) { 464 ((int[]) array)[index] = value; 465 } else if (array instanceof long[]) { 466 ((long[]) array)[index] = value; 467 } else if (array instanceof short[]) { 468 ((short[]) array)[index] = value; 469 } else { 470 throw badArray(array); 471 } 472 } 473 474 /** 475 * Sets {@code array[index] = value}. Applies to char, double, float, int, and long arrays. 476 * 477 * @throws NullPointerException if {@code array == null} 478 * @throws IllegalArgumentException 479 * if the {@code array} is not an array or the value cannot be 480 * converted to the array type by a widening conversion 481 * @throws ArrayIndexOutOfBoundsException 482 * if {@code index < 0 || index >= array.length} 483 */ 484 public static void setChar(Object array, int index, char value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 485 if (array instanceof char[]) { 486 ((char[]) array)[index] = value; 487 } else if (array instanceof double[]) { 488 ((double[]) array)[index] = value; 489 } else if (array instanceof float[]) { 490 ((float[]) array)[index] = value; 491 } else if (array instanceof int[]) { 492 ((int[]) array)[index] = value; 493 } else if (array instanceof long[]) { 494 ((long[]) array)[index] = value; 495 } else { 496 throw badArray(array); 497 } 498 } 499 500 /** 501 * Sets {@code array[index] = value}. Applies to double arrays. 502 * 503 * @throws NullPointerException if {@code array == null} 504 * @throws IllegalArgumentException 505 * if the {@code array} is not an array or the value cannot be 506 * converted to the array type by a widening conversion 507 * @throws ArrayIndexOutOfBoundsException 508 * if {@code index < 0 || index >= array.length} 509 */ 510 public static void setDouble(Object array, int index, double value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 511 if (array instanceof double[]) { 512 ((double[]) array)[index] = value; 513 } else { 514 throw badArray(array); 515 } 516 } 517 518 /** 519 * Sets {@code array[index] = value}. Applies to double and float arrays. 520 * 521 * @throws NullPointerException if {@code array == null} 522 * @throws IllegalArgumentException 523 * if the {@code array} is not an array or the value cannot be 524 * converted to the array type by a widening conversion 525 * @throws ArrayIndexOutOfBoundsException 526 * if {@code index < 0 || index >= array.length} 527 */ 528 public static void setFloat(Object array, int index, float value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 529 if (array instanceof float[]) { 530 ((float[]) array)[index] = value; 531 } else if (array instanceof double[]) { 532 ((double[]) array)[index] = value; 533 } else { 534 throw badArray(array); 535 } 536 } 537 538 /** 539 * Sets {@code array[index] = value}. Applies to double, float, int, and long arrays. 540 * 541 * @throws NullPointerException if {@code array == null} 542 * @throws IllegalArgumentException 543 * if the {@code array} is not an array or the value cannot be 544 * converted to the array type by a widening conversion 545 * @throws ArrayIndexOutOfBoundsException 546 * if {@code index < 0 || index >= array.length} 547 */ 548 public static void setInt(Object array, int index, int value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 549 if (array instanceof int[]) { 550 ((int[]) array)[index] = value; 551 } else if (array instanceof double[]) { 552 ((double[]) array)[index] = value; 553 } else if (array instanceof float[]) { 554 ((float[]) array)[index] = value; 555 } else if (array instanceof long[]) { 556 ((long[]) array)[index] = value; 557 } else { 558 throw badArray(array); 559 } 560 } 561 562 /** 563 * Sets {@code array[index] = value}. Applies to double, float, and long arrays. 564 * 565 * @throws NullPointerException if {@code array == null} 566 * @throws IllegalArgumentException 567 * if the {@code array} is not an array or the value cannot be 568 * converted to the array type by a widening conversion 569 * @throws ArrayIndexOutOfBoundsException 570 * if {@code index < 0 || index >= array.length} 571 */ 572 public static void setLong(Object array, int index, long value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 573 if (array instanceof long[]) { 574 ((long[]) array)[index] = value; 575 } else if (array instanceof double[]) { 576 ((double[]) array)[index] = value; 577 } else if (array instanceof float[]) { 578 ((float[]) array)[index] = value; 579 } else { 580 throw badArray(array); 581 } 582 } 583 584 /** 585 * Sets {@code array[index] = value}. Applies to double, float, int, long, and short arrays. 586 * 587 * @throws NullPointerException if {@code array == null} 588 * @throws IllegalArgumentException 589 * if the {@code array} is not an array or the value cannot be 590 * converted to the array type by a widening conversion 591 * @throws ArrayIndexOutOfBoundsException 592 * if {@code index < 0 || index >= array.length} 593 */ 594 public static void setShort(Object array, int index, short value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 595 if (array instanceof short[]) { 596 ((short[]) array)[index] = value; 597 } else if (array instanceof double[]) { 598 ((double[]) array)[index] = value; 599 } else if (array instanceof float[]) { 600 ((float[]) array)[index] = value; 601 } else if (array instanceof int[]) { 602 ((int[]) array)[index] = value; 603 } else if (array instanceof long[]) { 604 ((long[]) array)[index] = value; 605 } else { 606 throw badArray(array); 607 } 608 } 609 } 610