1 /* 2 * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.reflect; 27 28 import jdk.internal.vm.annotation.IntrinsicCandidate; 29 30 /** 31 * The {@code Array} class provides static methods to dynamically create and 32 * access Java arrays. 33 * 34 * <p>{@code Array} permits widening conversions to occur during a get or set 35 * operation, but throws an {@code IllegalArgumentException} if a narrowing 36 * conversion would occur. 37 * 38 * @author Nakul Saraiya 39 * @since 1.1 40 */ 41 public final 42 class Array { 43 44 /** 45 * Constructor. Class Array is not instantiable. 46 */ 47 private Array() {} 48 49 /** 50 * Creates a new array with the specified component type and 51 * length. 52 * @implSpec 53 * Invoking this method is equivalent to creating an array 54 * as follows: 55 * <blockquote> 56 * {@code Array.newInstance(componentType, new int[]{length});} 57 * </blockquote> 58 * 59 * <p>The number of dimensions of the new array must not 60 * exceed 255. 61 * 62 * @param componentType the {@code Class} object representing the 63 * component type of the new array 64 * @param length the length of the new array 65 * @return the new array 66 * @throws NullPointerException if the specified 67 * {@code componentType} parameter is null 68 * @throws IllegalArgumentException if componentType is {@link 69 * Void#TYPE} or if the number of dimensions of the requested array 70 * instance exceed 255. 71 * @throws NegativeArraySizeException if the specified {@code length} 72 * is negative 73 */ 74 public static Object newInstance(Class<?> componentType, int length) 75 throws NegativeArraySizeException { 76 return newArray(componentType, length); 77 } 78 79 /** 80 * Creates a new array 81 * with the specified component type and dimensions. 82 * If {@code componentType} 83 * represents a non-array class or interface, the new array 84 * has {@code dimensions.length} dimensions and 85 * {@code componentType} as its component type. If 86 * {@code componentType} represents an array class, the 87 * number of dimensions of the new array is equal to the sum 88 * of {@code dimensions.length} and the number of 89 * dimensions of {@code componentType}. In this case, the 90 * component type of the new array is the component type of 91 * {@code componentType}. 92 * 93 * <p>The number of dimensions of the new array must not 94 * exceed 255. 95 * 96 * @param componentType the {@code Class} object representing the component 97 * type of the new array 98 * @param dimensions an array of {@code int} representing the dimensions of 99 * the new array 100 * @return the new array 101 * @throws NullPointerException if the specified 102 * {@code componentType} argument is null 103 * @throws IllegalArgumentException if the specified {@code dimensions} 104 * argument is a zero-dimensional array, if componentType is {@link 105 * Void#TYPE}, or if the number of dimensions of the requested array 106 * instance exceed 255. 107 * @throws NegativeArraySizeException if any of the components in 108 * the specified {@code dimensions} argument is negative. 109 */ 110 public static Object newInstance(Class<?> componentType, int... dimensions) 111 throws IllegalArgumentException, NegativeArraySizeException { 112 return multiNewArray(componentType, dimensions); 113 } 114 115 /** 116 * Returns the length of the specified array object, as an {@code int}. 117 * 118 * @param array the array 119 * @return the length of the array 120 * @throws IllegalArgumentException if the object argument is not 121 * an array 122 */ 123 @IntrinsicCandidate 124 public static native int getLength(Object array) 125 throws IllegalArgumentException; 126 127 /** 128 * Returns the value of the indexed component in the specified 129 * array object. The value is automatically wrapped in an object 130 * if it has a primitive type. 131 * 132 * @param array the array 133 * @param index the index 134 * @return the (possibly wrapped) value of the indexed component in 135 * the specified array 136 * @throws NullPointerException If the specified object is null 137 * @throws IllegalArgumentException If the specified object is not 138 * an array 139 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 140 * argument is negative, or if it is greater than or equal to the 141 * length of the specified array 142 */ 143 public static Object get(Object array, int index) 144 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 145 Class<?> componentType = array.getClass().getComponentType(); 146 if (componentType != null && !componentType.isPrimitive()) { 147 Object[] objArray = (Object[]) array.getClass().cast(array); 148 return objArray[index]; 149 } else { 150 return getReferenceOrPrimitive(array, index); 151 } 152 } 153 154 private static native Object getReferenceOrPrimitive(Object array, int index); 155 156 /** 157 * Returns the value of the indexed component in the specified 158 * array object, as a {@code boolean}. 159 * 160 * @param array the array 161 * @param index the index 162 * @return the value of the indexed component in the specified array 163 * @throws NullPointerException If the specified object is null 164 * @throws IllegalArgumentException If the specified object is not 165 * an array, or if the indexed element cannot be converted to the 166 * return type by an identity or widening conversion 167 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 168 * argument is negative, or if it is greater than or equal to the 169 * length of the specified array 170 * @see Array#get 171 */ 172 public static native boolean getBoolean(Object array, int index) 173 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 174 175 /** 176 * Returns the value of the indexed component in the specified 177 * array object, as a {@code byte}. 178 * 179 * @param array the array 180 * @param index the index 181 * @return the value of the indexed component in the specified array 182 * @throws NullPointerException If the specified object is null 183 * @throws IllegalArgumentException If the specified object is not 184 * an array, or if the indexed element cannot be converted to the 185 * return type by an identity or widening conversion 186 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 187 * argument is negative, or if it is greater than or equal to the 188 * length of the specified array 189 * @see Array#get 190 */ 191 public static native byte getByte(Object array, int index) 192 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 193 194 /** 195 * Returns the value of the indexed component in the specified 196 * array object, as a {@code char}. 197 * 198 * @param array the array 199 * @param index the index 200 * @return the value of the indexed component in the specified array 201 * @throws NullPointerException If the specified object is null 202 * @throws IllegalArgumentException If the specified object is not 203 * an array, or if the indexed element cannot be converted to the 204 * return type by an identity or widening conversion 205 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 206 * argument is negative, or if it is greater than or equal to the 207 * length of the specified array 208 * @see Array#get 209 */ 210 public static native char getChar(Object array, int index) 211 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 212 213 /** 214 * Returns the value of the indexed component in the specified 215 * array object, as a {@code short}. 216 * 217 * @param array the array 218 * @param index the index 219 * @return the value of the indexed component in the specified array 220 * @throws NullPointerException If the specified object is null 221 * @throws IllegalArgumentException If the specified object is not 222 * an array, or if the indexed element cannot be converted to the 223 * return type by an identity or widening conversion 224 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 225 * argument is negative, or if it is greater than or equal to the 226 * length of the specified array 227 * @see Array#get 228 */ 229 public static native short getShort(Object array, int index) 230 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 231 232 /** 233 * Returns the value of the indexed component in the specified 234 * array object, as an {@code int}. 235 * 236 * @param array the array 237 * @param index the index 238 * @return the value of the indexed component in the specified array 239 * @throws NullPointerException If the specified object is null 240 * @throws IllegalArgumentException If the specified object is not 241 * an array, or if the indexed element cannot be converted to the 242 * return type by an identity or widening conversion 243 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 244 * argument is negative, or if it is greater than or equal to the 245 * length of the specified array 246 * @see Array#get 247 */ 248 public static native int getInt(Object array, int index) 249 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 250 251 /** 252 * Returns the value of the indexed component in the specified 253 * array object, as a {@code long}. 254 * 255 * @param array the array 256 * @param index the index 257 * @return the value of the indexed component in the specified array 258 * @throws NullPointerException If the specified object is null 259 * @throws IllegalArgumentException If the specified object is not 260 * an array, or if the indexed element cannot be converted to the 261 * return type by an identity or widening conversion 262 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 263 * argument is negative, or if it is greater than or equal to the 264 * length of the specified array 265 * @see Array#get 266 */ 267 public static native long getLong(Object array, int index) 268 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 269 270 /** 271 * Returns the value of the indexed component in the specified 272 * array object, as a {@code float}. 273 * 274 * @param array the array 275 * @param index the index 276 * @return the value of the indexed component in the specified array 277 * @throws NullPointerException If the specified object is null 278 * @throws IllegalArgumentException If the specified object is not 279 * an array, or if the indexed element cannot be converted to the 280 * return type by an identity or widening conversion 281 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 282 * argument is negative, or if it is greater than or equal to the 283 * length of the specified array 284 * @see Array#get 285 */ 286 public static native float getFloat(Object array, int index) 287 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 288 289 /** 290 * Returns the value of the indexed component in the specified 291 * array object, as a {@code double}. 292 * 293 * @param array the array 294 * @param index the index 295 * @return the value of the indexed component in the specified array 296 * @throws NullPointerException If the specified object is null 297 * @throws IllegalArgumentException If the specified object is not 298 * an array, or if the indexed element cannot be converted to the 299 * return type by an identity or widening conversion 300 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 301 * argument is negative, or if it is greater than or equal to the 302 * length of the specified array 303 * @see Array#get 304 */ 305 public static native double getDouble(Object array, int index) 306 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 307 308 /** 309 * Sets the value of the indexed component of the specified array 310 * object to the specified new value. The new value is first 311 * automatically unwrapped if the array has a primitive component 312 * type. 313 * @param array the array 314 * @param index the index into the array 315 * @param value the new value of the indexed component 316 * @throws NullPointerException If the specified object argument 317 * is null 318 * @throws IllegalArgumentException If the specified object argument 319 * is not an array, or if the array component type is primitive and 320 * an unwrapping conversion fails 321 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 322 * argument is negative, or if it is greater than or equal to 323 * the length of the specified array 324 */ 325 public static void set(Object array, int index, Object value) 326 throws IllegalArgumentException, ArrayIndexOutOfBoundsException { 327 Class<?> componentType = array.getClass().getComponentType(); 328 if (componentType != null && !componentType.isPrimitive()) { 329 Object[] objArray = (Object[]) array.getClass().cast(array); 330 objArray[index] = componentType.cast(value); 331 } else { 332 setReferenceOrPrimitive(array, index, value); 333 } 334 } 335 336 private static native void setReferenceOrPrimitive(Object array, int index, Object value); 337 338 /** 339 * Sets the value of the indexed component of the specified array 340 * object to the specified {@code boolean} value. 341 * @param array the array 342 * @param index the index into the array 343 * @param z the new value of the indexed component 344 * @throws NullPointerException If the specified object argument 345 * is null 346 * @throws IllegalArgumentException If the specified object argument 347 * is not an array, or if the specified value cannot be converted 348 * to the underlying array's component type by an identity or a 349 * primitive widening conversion 350 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 351 * argument is negative, or if it is greater than or equal to 352 * the length of the specified array 353 * @see Array#set 354 */ 355 public static native void setBoolean(Object array, int index, boolean z) 356 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 357 358 /** 359 * Sets the value of the indexed component of the specified array 360 * object to the specified {@code byte} value. 361 * @param array the array 362 * @param index the index into the array 363 * @param b the new value of the indexed component 364 * @throws NullPointerException If the specified object argument 365 * is null 366 * @throws IllegalArgumentException If the specified object argument 367 * is not an array, or if the specified value cannot be converted 368 * to the underlying array's component type by an identity or a 369 * primitive widening conversion 370 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 371 * argument is negative, or if it is greater than or equal to 372 * the length of the specified array 373 * @see Array#set 374 */ 375 public static native void setByte(Object array, int index, byte b) 376 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 377 378 /** 379 * Sets the value of the indexed component of the specified array 380 * object to the specified {@code char} value. 381 * @param array the array 382 * @param index the index into the array 383 * @param c the new value of the indexed component 384 * @throws NullPointerException If the specified object argument 385 * is null 386 * @throws IllegalArgumentException If the specified object argument 387 * is not an array, or if the specified value cannot be converted 388 * to the underlying array's component type by an identity or a 389 * primitive widening conversion 390 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 391 * argument is negative, or if it is greater than or equal to 392 * the length of the specified array 393 * @see Array#set 394 */ 395 public static native void setChar(Object array, int index, char c) 396 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 397 398 /** 399 * Sets the value of the indexed component of the specified array 400 * object to the specified {@code short} value. 401 * @param array the array 402 * @param index the index into the array 403 * @param s the new value of the indexed component 404 * @throws NullPointerException If the specified object argument 405 * is null 406 * @throws IllegalArgumentException If the specified object argument 407 * is not an array, or if the specified value cannot be converted 408 * to the underlying array's component type by an identity or a 409 * primitive widening conversion 410 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 411 * argument is negative, or if it is greater than or equal to 412 * the length of the specified array 413 * @see Array#set 414 */ 415 public static native void setShort(Object array, int index, short s) 416 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 417 418 /** 419 * Sets the value of the indexed component of the specified array 420 * object to the specified {@code int} value. 421 * @param array the array 422 * @param index the index into the array 423 * @param i the new value of the indexed component 424 * @throws NullPointerException If the specified object argument 425 * is null 426 * @throws IllegalArgumentException If the specified object argument 427 * is not an array, or if the specified value cannot be converted 428 * to the underlying array's component type by an identity or a 429 * primitive widening conversion 430 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 431 * argument is negative, or if it is greater than or equal to 432 * the length of the specified array 433 * @see Array#set 434 */ 435 public static native void setInt(Object array, int index, int i) 436 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 437 438 /** 439 * Sets the value of the indexed component of the specified array 440 * object to the specified {@code long} value. 441 * @param array the array 442 * @param index the index into the array 443 * @param l the new value of the indexed component 444 * @throws NullPointerException If the specified object argument 445 * is null 446 * @throws IllegalArgumentException If the specified object argument 447 * is not an array, or if the specified value cannot be converted 448 * to the underlying array's component type by an identity or a 449 * primitive widening conversion 450 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 451 * argument is negative, or if it is greater than or equal to 452 * the length of the specified array 453 * @see Array#set 454 */ 455 public static native void setLong(Object array, int index, long l) 456 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 457 458 /** 459 * Sets the value of the indexed component of the specified array 460 * object to the specified {@code float} value. 461 * @param array the array 462 * @param index the index into the array 463 * @param f the new value of the indexed component 464 * @throws NullPointerException If the specified object argument 465 * is null 466 * @throws IllegalArgumentException If the specified object argument 467 * is not an array, or if the specified value cannot be converted 468 * to the underlying array's component type by an identity or a 469 * primitive widening conversion 470 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 471 * argument is negative, or if it is greater than or equal to 472 * the length of the specified array 473 * @see Array#set 474 */ 475 public static native void setFloat(Object array, int index, float f) 476 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 477 478 /** 479 * Sets the value of the indexed component of the specified array 480 * object to the specified {@code double} value. 481 * @param array the array 482 * @param index the index into the array 483 * @param d the new value of the indexed component 484 * @throws NullPointerException If the specified object argument 485 * is null 486 * @throws IllegalArgumentException If the specified object argument 487 * is not an array, or if the specified value cannot be converted 488 * to the underlying array's component type by an identity or a 489 * primitive widening conversion 490 * @throws ArrayIndexOutOfBoundsException If the specified {@code index} 491 * argument is negative, or if it is greater than or equal to 492 * the length of the specified array 493 * @see Array#set 494 */ 495 public static native void setDouble(Object array, int index, double d) 496 throws IllegalArgumentException, ArrayIndexOutOfBoundsException; 497 498 /* 499 * Private 500 */ 501 502 @IntrinsicCandidate 503 private static native Object newArray(Class<?> componentType, int length) 504 throws NegativeArraySizeException; 505 506 private static native Object multiNewArray(Class<?> componentType, 507 int[] dimensions) 508 throws IllegalArgumentException, NegativeArraySizeException; 509 510 511 }