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             objArray[index] = componentType.cast(value);
 334         } else {
 335             setReferenceOrPrimitive(array, index, value);
 336         }
 337     }
 338 
 339     private static native void setReferenceOrPrimitive(Object array, int index, Object value);
 340 
 341     /**
 342      * Sets the value of the indexed component of the specified array
 343      * object to the specified {@code boolean} value.
 344      * @param array the array
 345      * @param index the index into the array
 346      * @param z the new value of the indexed component
 347      * @exception NullPointerException If the specified object argument
 348      * is null
 349      * @exception IllegalArgumentException If the specified object argument
 350      * is not an array, or if the specified value cannot be converted
 351      * to the underlying array's component type by an identity or a
 352      * primitive widening conversion
 353      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 354      * argument is negative, or if it is greater than or equal to
 355      * the length of the specified array
 356      * @see Array#set
 357      */
 358     public static native void setBoolean(Object array, int index, boolean z)
 359         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 360 
 361     /**
 362      * Sets the value of the indexed component of the specified array
 363      * object to the specified {@code byte} value.
 364      * @param array the array
 365      * @param index the index into the array
 366      * @param b the new value of the indexed component
 367      * @exception NullPointerException If the specified object argument
 368      * is null
 369      * @exception IllegalArgumentException If the specified object argument
 370      * is not an array, or if the specified value cannot be converted
 371      * to the underlying array's component type by an identity or a
 372      * primitive widening conversion
 373      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 374      * argument is negative, or if it is greater than or equal to
 375      * the length of the specified array
 376      * @see Array#set
 377      */
 378     public static native void setByte(Object array, int index, byte b)
 379         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 380 
 381     /**
 382      * Sets the value of the indexed component of the specified array
 383      * object to the specified {@code char} value.
 384      * @param array the array
 385      * @param index the index into the array
 386      * @param c the new value of the indexed component
 387      * @exception NullPointerException If the specified object argument
 388      * is null
 389      * @exception IllegalArgumentException If the specified object argument
 390      * is not an array, or if the specified value cannot be converted
 391      * to the underlying array's component type by an identity or a
 392      * primitive widening conversion
 393      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 394      * argument is negative, or if it is greater than or equal to
 395      * the length of the specified array
 396      * @see Array#set
 397      */
 398     public static native void setChar(Object array, int index, char c)
 399         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 400 
 401     /**
 402      * Sets the value of the indexed component of the specified array
 403      * object to the specified {@code short} value.
 404      * @param array the array
 405      * @param index the index into the array
 406      * @param s the new value of the indexed component
 407      * @exception NullPointerException If the specified object argument
 408      * is null
 409      * @exception IllegalArgumentException If the specified object argument
 410      * is not an array, or if the specified value cannot be converted
 411      * to the underlying array's component type by an identity or a
 412      * primitive widening conversion
 413      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 414      * argument is negative, or if it is greater than or equal to
 415      * the length of the specified array
 416      * @see Array#set
 417      */
 418     public static native void setShort(Object array, int index, short s)
 419         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 420 
 421     /**
 422      * Sets the value of the indexed component of the specified array
 423      * object to the specified {@code int} value.
 424      * @param array the array
 425      * @param index the index into the array
 426      * @param i the new value of the indexed component
 427      * @exception NullPointerException If the specified object argument
 428      * is null
 429      * @exception IllegalArgumentException If the specified object argument
 430      * is not an array, or if the specified value cannot be converted
 431      * to the underlying array's component type by an identity or a
 432      * primitive widening conversion
 433      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 434      * argument is negative, or if it is greater than or equal to
 435      * the length of the specified array
 436      * @see Array#set
 437      */
 438     public static native void setInt(Object array, int index, int i)
 439         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 440 
 441     /**
 442      * Sets the value of the indexed component of the specified array
 443      * object to the specified {@code long} value.
 444      * @param array the array
 445      * @param index the index into the array
 446      * @param l the new value of the indexed component
 447      * @exception NullPointerException If the specified object argument
 448      * is null
 449      * @exception IllegalArgumentException If the specified object argument
 450      * is not an array, or if the specified value cannot be converted
 451      * to the underlying array's component type by an identity or a
 452      * primitive widening conversion
 453      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 454      * argument is negative, or if it is greater than or equal to
 455      * the length of the specified array
 456      * @see Array#set
 457      */
 458     public static native void setLong(Object array, int index, long l)
 459         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 460 
 461     /**
 462      * Sets the value of the indexed component of the specified array
 463      * object to the specified {@code float} value.
 464      * @param array the array
 465      * @param index the index into the array
 466      * @param f the new value of the indexed component
 467      * @exception NullPointerException If the specified object argument
 468      * is null
 469      * @exception IllegalArgumentException If the specified object argument
 470      * is not an array, or if the specified value cannot be converted
 471      * to the underlying array's component type by an identity or a
 472      * primitive widening conversion
 473      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 474      * argument is negative, or if it is greater than or equal to
 475      * the length of the specified array
 476      * @see Array#set
 477      */
 478     public static native void setFloat(Object array, int index, float f)
 479         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 480 
 481     /**
 482      * Sets the value of the indexed component of the specified array
 483      * object to the specified {@code double} value.
 484      * @param array the array
 485      * @param index the index into the array
 486      * @param d the new value of the indexed component
 487      * @exception NullPointerException If the specified object argument
 488      * is null
 489      * @exception IllegalArgumentException If the specified object argument
 490      * is not an array, or if the specified value cannot be converted
 491      * to the underlying array's component type by an identity or a
 492      * primitive widening conversion
 493      * @exception ArrayIndexOutOfBoundsException If the specified {@code index}
 494      * argument is negative, or if it is greater than or equal to
 495      * the length of the specified array
 496      * @see Array#set
 497      */
 498     public static native void setDouble(Object array, int index, double d)
 499         throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
 500 
 501     /*
 502      * Private
 503      */
 504 
 505     @HotSpotIntrinsicCandidate
 506     private static native Object newArray(Class<?> componentType, int length)
 507         throws NegativeArraySizeException;
 508 
 509     private static native Object multiNewArray(Class<?> componentType,
 510         int[] dimensions)
 511         throws IllegalArgumentException, NegativeArraySizeException;
 512 
 513 
 514 }