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