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 * This class provides static methods to create and access arrays dynamically. 37 */ 38 public final class Array { 39 40 /** 41 * Prevent this class from being instantiated. 42 */ 43 private Array(){ 44 //do nothing 45 } 46 47 /** 48 * Returns the element of the array at the specified index. This reproduces 49 * the effect of {@code array[index]}. If the array component is a primitive 50 * type, the result is automatically boxed. 51 * 52 * @param array 53 * the array 54 * @param index 55 * the index 56 * 57 * @return the requested element, possibly boxed 58 * 59 * @throws NullPointerException 60 * if the array is null 61 * @throws IllegalArgumentException 62 * if {@code array} is not an array 63 * @throws ArrayIndexOutOfBoundsException 64 * if {@code index < 0 || index >= array.length} 65 */ 66 public static Object get(Object array, int index) 67 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 68 if (array instanceof Object[]) 69 return ((Object[]) array)[index]; 70 71 if (array instanceof boolean[]) 72 return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE; 73 74 if (array instanceof byte[]) 75 return Byte.valueOf(((byte[]) array)[index]); 76 77 if (array instanceof char[]) 78 return Character.valueOf(((char[]) array)[index]); 79 80 if (array instanceof short[]) 81 return Short.valueOf(((short[]) array)[index]); 82 83 if (array instanceof int[]) 84 return Integer.valueOf(((int[]) array)[index]); 85 86 if (array instanceof long[]) 87 return Long.valueOf(((long[]) array)[index]); 88 89 if (array instanceof float[]) 90 return new Float(((float[]) array)[index]); 91 92 if (array instanceof double[]) 93 return new Double(((double[]) array)[index]); 94 95 if (array == null) 96 throw new NullPointerException(); 97 98 throw new IllegalArgumentException("Not an array"); 99 } 100 101 /** 102 * Returns the element of the array at the specified index, converted to a 103 * {@code boolean}, if possible. This reproduces the effect of {@code 104 * array[index]} 105 * 106 * @param array 107 * the array 108 * @param index 109 * the index 110 * 111 * @return the requested element 112 * 113 * @throws NullPointerException 114 * if the {@code array} is {@code null} 115 * @throws IllegalArgumentException 116 * if {@code array} is not an array or the element at the 117 * index position can not be converted to the return type 118 * @throws ArrayIndexOutOfBoundsException 119 * if {@code index < 0 || index >= array.length} 120 */ 121 public static boolean getBoolean(Object array, int index) 122 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 123 if (array instanceof boolean[]) { 124 return ((boolean[]) array)[index]; 125 } else if (array == null) { 126 throw new NullPointerException(); 127 } else if (array.getClass().isArray()) { 128 throw new IllegalArgumentException("Wrong array type"); 129 } else { 130 throw new IllegalArgumentException("Not an array"); 131 } 132 } 133 134 /** 135 * Returns the element of the array at the specified index, converted to a 136 * {@code byte}, if possible. This reproduces the effect of {@code 137 * array[index]} 138 * 139 * @param array 140 * the array 141 * @param index 142 * the index 143 * 144 * @return the requested element 145 * 146 * @throws NullPointerException 147 * if the {@code array} is {@code null} 148 * @throws IllegalArgumentException 149 * if {@code array} is not an array or the element at the 150 * index position can not be converted to the return type 151 * @throws ArrayIndexOutOfBoundsException 152 * if {@code index < 0 || index >= array.length} 153 */ 154 public static byte getByte(Object array, int index) 155 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 156 if (array instanceof byte[]) { 157 return ((byte[]) array)[index]; 158 } else { 159 return getBoolean(array, index) ? (byte)1 : (byte)0; 160 } 161 } 162 163 /** 164 * Returns the element of the array at the specified index, converted to a 165 * {@code char}, if possible. This reproduces the effect of {@code 166 * array[index]} 167 * 168 * @param array 169 * the array 170 * @param index 171 * the index 172 * 173 * @return the requested element 174 * 175 * @throws NullPointerException 176 * if the {@code array} is {@code null} 177 * @throws IllegalArgumentException 178 * if {@code array} is not an array or the element at the 179 * index position can not be converted to the return type 180 * @throws ArrayIndexOutOfBoundsException 181 * if {@code index < 0 || index >= array.length} 182 */ 183 public static char getChar(Object array, int index) 184 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 185 if (array instanceof char[]) { 186 return ((char[]) array)[index]; 187 } else if (array == null) { 188 throw new NullPointerException(); 189 } else if (array.getClass().isArray()) { 190 throw new IllegalArgumentException("Wrong array type"); 191 } else { 192 throw new IllegalArgumentException("Not an array"); 193 } 194 } 195 196 /** 197 * Returns the element of the array at the specified index, converted to a 198 * {@code double}, if possible. This reproduces the effect of {@code 199 * array[index]} 200 * 201 * @param array 202 * the array 203 * @param index 204 * the index 205 * 206 * @return the requested element 207 * 208 * @throws NullPointerException 209 * if the {@code array} is {@code null} 210 * @throws IllegalArgumentException 211 * if {@code array} is not an array or the element at the 212 * index position can not be converted to the return type 213 * @throws ArrayIndexOutOfBoundsException 214 * if {@code index < 0 || index >= array.length} 215 */ 216 public static double getDouble(Object array, int index) 217 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 218 if (array instanceof double[]) { 219 return ((double[]) array)[index]; 220 } else { 221 return getFloat(array, index); 222 } 223 } 224 225 /** 226 * Returns the element of the array at the specified index, converted to a 227 * {@code float}, if possible. This reproduces the effect of {@code 228 * array[index]} 229 * 230 * @param array 231 * the array 232 * @param index 233 * the index 234 * 235 * @return the requested element 236 * 237 * @throws NullPointerException 238 * if the {@code array} is {@code null} 239 * @throws IllegalArgumentException 240 * if {@code array} is not an array or the element at the 241 * index position can not be converted to the return type 242 * @throws ArrayIndexOutOfBoundsException 243 * if {@code index < 0 || index >= array.length} 244 */ 245 public static float getFloat(Object array, int index) 246 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 247 if (array instanceof float[]) { 248 return ((float[]) array)[index]; 249 } else { 250 return getLong(array, index); 251 } 252 } 253 254 /** 255 * Returns the element of the array at the specified index, converted to an 256 * {@code int}, if possible. This reproduces the effect of {@code 257 * array[index]} 258 * 259 * @param array 260 * the array 261 * @param index 262 * the index 263 * 264 * @return the requested element 265 * 266 * @throws NullPointerException 267 * if the {@code array} is {@code null} 268 * @throws IllegalArgumentException 269 * if {@code array} is not an array or the element at the 270 * index position can not be converted to the return type 271 * @throws ArrayIndexOutOfBoundsException 272 * if {@code index < 0 || index >= array.length} 273 */ 274 public static int getInt(Object array, int index) 275 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 276 if (array instanceof int[]) { 277 return ((int[]) array)[index]; 278 } else { 279 return getShort(array, index); 280 } 281 } 282 283 /** 284 * Returns the length of the array. This reproduces the effect of {@code 285 * array.length} 286 * 287 * @param array 288 * the array 289 * 290 * @return the length of the array 291 * 292 * @throws NullPointerException 293 * if the {@code array} is {@code null} 294 * @throws IllegalArgumentException 295 * if {@code array} is not an array 296 */ 297 public static int getLength(Object array) { 298 if (array instanceof Object[]) 299 return ((Object[]) array).length; 300 301 if (array instanceof boolean[]) 302 return ((boolean[]) array).length; 303 304 if (array instanceof byte[]) 305 return ((byte[]) array).length; 306 307 if (array instanceof char[]) 308 return ((char[]) array).length; 309 310 if (array instanceof short[]) 311 return ((short[]) array).length; 312 313 if (array instanceof int[]) 314 return ((int[]) array).length; 315 316 if (array instanceof long[]) 317 return ((long[]) array).length; 318 319 if (array instanceof float[]) 320 return ((float[]) array).length; 321 322 if (array instanceof double[]) 323 return ((double[]) array).length; 324 325 if (array == null) 326 throw new NullPointerException(); 327 328 throw new IllegalArgumentException("Not an array"); 329 } 330 331 /** 332 * Returns the element of the array at the specified index, converted to a 333 * {@code long}, if possible. This reproduces the effect of {@code 334 * array[index]} 335 * 336 * @param array 337 * the array 338 * @param index 339 * the index 340 * 341 * @return the requested element 342 * 343 * @throws NullPointerException 344 * if the {@code array} is {@code null} 345 * @throws IllegalArgumentException 346 * if {@code array} is not an array or the element at the 347 * index position can not be converted to the return type 348 * @throws ArrayIndexOutOfBoundsException 349 * if {@code index < 0 || index >= array.length} 350 */ 351 public static long getLong(Object array, int index) 352 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 353 if (array instanceof long[]) { 354 return ((long[]) array)[index]; 355 } else { 356 return getInt(array, index); 357 } 358 } 359 360 /** 361 * Returns the element of the array at the specified index, converted to a 362 * {@code short}, if possible. This reproduces the effect of {@code 363 * array[index]} 364 * 365 * @param array 366 * the array 367 * @param index 368 * the index 369 * 370 * @return the requested element 371 * 372 * @throws NullPointerException 373 * if the {@code array} is {@code null} 374 * @throws IllegalArgumentException 375 * if {@code array} is not an array or the element at the 376 * index position can not be converted to the return type 377 * @throws ArrayIndexOutOfBoundsException 378 * if {@code index < 0 || index >= array.length} 379 */ 380 public static short getShort(Object array, int index) 381 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 382 if (array instanceof short[]) 383 return ((short[]) array)[index]; 384 385 return getByte(array, index); 386 } 387 388 /** 389 * Returns a new multidimensional array of the specified component type and 390 * dimensions. This reproduces the effect of {@code new 391 * componentType[d0][d1]...[dn]} for a dimensions array of { d0, d1, ... , 392 * dn }. 393 * 394 * @param componentType 395 * the component type of the new array 396 * @param dimensions 397 * the dimensions of the new array 398 * 399 * @return the new array 400 * 401 * @throws NullPointerException 402 * if the component type is {@code null} 403 * @throws NegativeArraySizeException 404 * if any of the dimensions are negative 405 * @throws IllegalArgumentException 406 * if the array of dimensions is of size zero, or exceeds the 407 * limit of the number of dimension for an array (currently 255) 408 */ 409 public static Object newInstance(Class<?> componentType, int... dimensions) 410 throws NegativeArraySizeException, IllegalArgumentException { 411 if (dimensions.length <= 0 || dimensions.length > 255) 412 throw new IllegalArgumentException("Bad number of dimensions"); 413 414 if (componentType == void.class) 415 throw new IllegalArgumentException(); 416 417 if (componentType == null) 418 throw new NullPointerException(); 419 420 return createMultiArray(componentType, dimensions); 421 } 422 423 /* 424 * Create a multi-dimensional array of objects with the specified type. 425 */ 426 native private static Object createMultiArray(Class<?> componentType, 427 int[] dimensions) throws NegativeArraySizeException; 428 429 /** 430 * Returns a new array of the specified component type and length. This 431 * reproduces the effect of {@code new componentType[size]}. 432 * 433 * @param componentType 434 * the component type of the new array 435 * @param size 436 * the length of the new array 437 * 438 * @return the new array 439 * 440 * @throws NullPointerException 441 * if the component type is null 442 * @throws NegativeArraySizeException 443 * if {@code size < 0} 444 */ 445 public static Object newInstance(Class<?> componentType, int size) 446 throws NegativeArraySizeException { 447 if (!componentType.isPrimitive()) { 448 return createObjectArray(componentType, size); 449 } 450 if (componentType == boolean.class) { 451 return new boolean[size]; 452 } 453 if (componentType == byte.class) { 454 return new byte[size]; 455 } 456 if (componentType == char.class) { 457 return new char[size]; 458 } 459 if (componentType == short.class) { 460 return new short[size]; 461 } 462 if (componentType == int.class) { 463 return new int[size]; 464 } 465 if (componentType == long.class) { 466 return new long[size]; 467 } 468 if (componentType == float.class) { 469 return new float[size]; 470 } 471 if (componentType == double.class) { 472 return new double[size]; 473 } 474 if (componentType == void.class) { 475 throw new IllegalArgumentException(); 476 } 477 throw new AssertionError(); 478 } 479 480 /* 481 * Create a one-dimensional array of objects with the specified type. 482 */ 483 native private static Object createObjectArray(Class<?> componentType, 484 int length) throws NegativeArraySizeException; 485 486 /** 487 * Sets the element of the array at the specified index to the value. This 488 * reproduces the effect of {@code array[index] = value}. If the array 489 * component is a primitive type, the value is automatically unboxed. 490 * 491 * @param array 492 * the array 493 * @param index 494 * the index 495 * @param value 496 * the new value 497 * 498 * @throws NullPointerException 499 * if the {@code array} is {@code null} 500 * @throws IllegalArgumentException 501 * if {@code array} is not an array or the value cannot be 502 * converted to the array type by a widening conversion 503 * @throws ArrayIndexOutOfBoundsException 504 * if {@code index < 0 || index >= array.length} 505 */ 506 public static void set(Object array, int index, Object value) 507 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 508 if (!array.getClass().isArray()) { 509 throw new IllegalArgumentException("Not an array type"); 510 } 511 512 if (array instanceof Object[]) { 513 if (value != null && 514 !array.getClass().getComponentType().isInstance(value)) { 515 // incompatible object type for this array 516 throw new IllegalArgumentException("Wrong array type"); 517 } 518 519 ((Object[]) array)[index] = value; 520 } else { 521 if (value == null) { 522 throw new IllegalArgumentException("Primitive array can't take null values."); 523 } 524 525 if (value instanceof Boolean) 526 setBoolean(array, index, ((Boolean) value).booleanValue()); 527 else if (value instanceof Byte) 528 setByte(array, index, ((Byte) value).byteValue()); 529 else if (value instanceof Character) 530 setChar(array, index, ((Character) value).charValue()); 531 else if (value instanceof Short) 532 setShort(array, index, ((Short) value).shortValue()); 533 else if (value instanceof Integer) 534 setInt(array, index, ((Integer) value).intValue()); 535 else if (value instanceof Long) 536 setLong(array, index, ((Long) value).longValue()); 537 else if (value instanceof Float) 538 setFloat(array, index, ((Float) value).floatValue()); 539 else if (value instanceof Double) 540 setDouble(array, index, ((Double) value).doubleValue()); 541 } 542 } 543 544 /** 545 * Sets the element of the array at the specified index to the {@code 546 * boolean} value. This reproduces the effect of {@code array[index] = 547 * value}. 548 * 549 * @param array 550 * the array 551 * @param index 552 * the index 553 * @param value 554 * the new value 555 * 556 * @throws NullPointerException 557 * if the {@code array} is {@code null} 558 * @throws IllegalArgumentException 559 * if the {@code array} is not an array or the value cannot be 560 * converted to the array type by a widening conversion 561 * @throws ArrayIndexOutOfBoundsException 562 * if {@code index < 0 || index >= array.length} 563 */ 564 public static void setBoolean(Object array, int index, boolean value) { 565 if (array instanceof boolean[]) { 566 ((boolean[]) array)[index] = value; 567 } else { 568 setByte(array, index, value ? (byte)1 : (byte)0); 569 } 570 } 571 572 /** 573 * Sets the element of the array at the specified index to the {@code byte} 574 * value. This reproduces the effect of {@code array[index] = value}. 575 * 576 * @param array 577 * the array 578 * @param index 579 * the index 580 * @param value 581 * the new value 582 * 583 * @throws NullPointerException 584 * if the {@code array} is {@code null} 585 * @throws IllegalArgumentException 586 * if the {@code array} is not an array or the value cannot be 587 * converted to the array type by a widening conversion 588 * @throws ArrayIndexOutOfBoundsException 589 * if {@code index < 0 || index >= array.length} 590 */ 591 public static void setByte(Object array, int index, byte value) 592 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 593 if (array instanceof byte[]) { 594 ((byte[]) array)[index] = value; 595 } else { 596 setShort(array, index, value); 597 } 598 } 599 600 /** 601 * Set the element of the array at the specified index to the {@code char} 602 * value. This reproduces the effect of {@code array[index] = value}. 603 * 604 * @param array 605 * the array 606 * @param index 607 * the index 608 * @param value 609 * the new value 610 * 611 * @throws NullPointerException 612 * if the {@code array} is {@code null} 613 * @throws IllegalArgumentException 614 * if the {@code array} is not an array or the value cannot be 615 * converted to the array type by a widening conversion 616 * @throws ArrayIndexOutOfBoundsException 617 * if {@code index < 0 || index >= array.length} 618 */ 619 public static void setChar(Object array, int index, char value) 620 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 621 if (array instanceof char[]) { 622 ((char[]) array)[index] = value; 623 } else if (array == null) { 624 throw new NullPointerException(); 625 } else if (!array.getClass().isArray()) { 626 throw new IllegalArgumentException("Not an array"); 627 } else { 628 throw new IllegalArgumentException("Wrong array type"); 629 } 630 } 631 632 /** 633 * Set the element of the array at the specified index to the {@code double} 634 * value. This reproduces the effect of {@code array[index] = value}. 635 * 636 * @param array 637 * the array 638 * @param index 639 * the index 640 * @param value 641 * the new value 642 * 643 * @throws NullPointerException 644 * if the {@code array} is {@code null} 645 * @throws IllegalArgumentException 646 * if the {@code array} is not an array or the value cannot be 647 * converted to the array type by a widening conversion 648 * @throws ArrayIndexOutOfBoundsException 649 * if {@code index < 0 || index >= array.length} 650 */ 651 public static void setDouble(Object array, int index, double value) 652 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 653 if (array instanceof double[]) { 654 ((double[]) array)[index] = value; 655 } else if (array == null) { 656 throw new NullPointerException(); 657 } else if (!array.getClass().isArray()) { 658 throw new IllegalArgumentException("Not an array"); 659 } else { 660 throw new IllegalArgumentException("Wrong array type"); 661 } 662 } 663 664 /** 665 * Set the element of the array at the specified index to the {@code float} 666 * value. This reproduces the effect of {@code array[index] = value}. 667 * 668 * @param array 669 * the array 670 * @param index 671 * the index 672 * @param value 673 * the new value 674 * 675 * @throws NullPointerException 676 * if the {@code array} is {@code null} 677 * @throws IllegalArgumentException 678 * if the {@code array} is not an array or the value cannot be 679 * converted to the array type by a widening conversion 680 * @throws ArrayIndexOutOfBoundsException 681 * if {@code index < 0 || index >= array.length} 682 */ 683 public static void setFloat(Object array, int index, float value) 684 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 685 if (array instanceof float[]) { 686 ((float[]) array)[index] = value; 687 } else { 688 setDouble(array, index, value); 689 } 690 } 691 692 /** 693 * Set the element of the array at the specified index to the {@code int} 694 * value. This reproduces the effect of {@code array[index] = value}. 695 * 696 * @param array 697 * the array 698 * @param index 699 * the index 700 * @param value 701 * the new value 702 * 703 * @throws NullPointerException 704 * if the {@code array} is {@code null} 705 * @throws IllegalArgumentException 706 * if the {@code array} is not an array or the value cannot be 707 * converted to the array type by a widening conversion 708 * @throws ArrayIndexOutOfBoundsException 709 * if {@code index < 0 || index >= array.length} 710 */ 711 public static void setInt(Object array, int index, int value) 712 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 713 if (array instanceof int[]) { 714 ((int[]) array)[index] = value; 715 } else { 716 setLong(array, index, value); 717 } 718 } 719 720 /** 721 * Set the element of the array at the specified index to the {@code long} 722 * value. This reproduces the effect of {@code array[index] = value}. 723 * 724 * @param array 725 * the array 726 * @param index 727 * the index 728 * @param value 729 * the new value 730 * 731 * @throws NullPointerException 732 * if the {@code array} is {@code null} 733 * @throws IllegalArgumentException 734 * if the {@code array} is not an array or the value cannot be 735 * converted to the array type by a widening conversion 736 * @throws ArrayIndexOutOfBoundsException 737 * if {@code index < 0 || index >= array.length} 738 */ 739 public static void setLong(Object array, int index, long value) 740 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 741 if (array instanceof long[]) { 742 ((long[]) array)[index] = value; 743 } else { 744 setFloat(array, index, value); 745 } 746 } 747 748 /** 749 * Set the element of the array at the specified index to the {@code short} 750 * value. This reproduces the effect of {@code array[index] = value}. 751 * 752 * @param array 753 * the array 754 * @param index 755 * the index 756 * @param value 757 * the new value 758 * 759 * @throws NullPointerException 760 * if the {@code array} is {@code null} 761 * @throws IllegalArgumentException 762 * if the {@code array} is not an array or the value cannot be 763 * converted to the array type by a widening conversion 764 * @throws ArrayIndexOutOfBoundsException 765 * if {@code index < 0 || index >= array.length} 766 */ 767 public static void setShort(Object array, int index, short value) 768 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 769 if (array instanceof short[]) { 770 ((short[]) array)[index] = value; 771 } else { 772 setInt(array, index, value); 773 } 774 } 775 776 } 777