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