Java反射—Array類的使用

有關Java反射的另外的文章:http://m.itdecent.cn/nb/29780510
不用說大家也知道java.lang.Array是對Java反射包中數(shù)組操作的一個類。JavaSE8的文檔中對Array的描述是這樣說的:

The Array class provides static methods to dynamically create and access Java arrays.

Array類提供靜態(tài)方法來動態(tài)創(chuàng)建和訪問Java數(shù)組。訪問不難理解,動態(tài)創(chuàng)建可以細看一下。

讓我們先看看java.util.Arrays

  • 注意是Arrays,相信有些小伙伴已經(jīng)用過很多次這個工具類了,提供了很多對數(shù)組操作的方法方便我們使用。

  • 上面說了java.lang.Array是提供給我們靜態(tài)方法來動態(tài)創(chuàng)建和訪問數(shù)組。讓我們來看看Arrays中的copyOf方式是怎么來動態(tài)操作數(shù)組的吧。

    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
    

    copyOf是拿來干嘛的呢?Arrays主要提供這個方法來給已經(jīng)填滿的數(shù)組來拓展數(shù)組大小的。

    你可以這樣用

    User[] users = new User[10];
    ...//假如滿了,給數(shù)組長度翻倍。
    users = Arrays.copyOf(users, users.length * 2);
    

    不知道大家有沒有注意到,這個方法是個泛型的返回結(jié)果。它的第一個參數(shù)是原始數(shù)組,第二個參數(shù)為新的長度,返回的是調(diào)用了另一個重載的copyOf方法,讓我們來看看這個重載的copyOf方法吧。

    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
    

    里面的調(diào)用不難理解,就是如果傳進來的original對象數(shù)組的Class和Object[]的Class相等那就直接new Object[]如果不相等就調(diào)用java.lang.reflect.Array中的newInstance方法進行創(chuàng)建新數(shù)組,后面調(diào)用的是System.arraycopy方法的作用源碼中的注釋是:Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array. 意思是:從指定的數(shù)組的制定位置開始復制到目標數(shù)組的指定位置。

為什么要用反射實現(xiàn)數(shù)組的擴展

  • 我們來看一下不用反射實現(xiàn)的"copyOf"

    private static Object[] badCopyOf(Object[] arr, int newLength) {
        Object[] newArray = new Object[newLength];
        System.arraycopy(arr, 0, newArray, 0, Math.min(arr.length, newLength));
        return newArray;
    }
    

    如果沒有上面那個ArrayscopyOf方法可能很多人會直接瀟瀟灑灑寫出如上代碼。不過有沒有想過一個問題,他能不能轉(zhuǎn)型成對應的你想用的類?這樣說,一個MyObject[]類轉(zhuǎn)成Object[],然后再轉(zhuǎn)回來是可以的,但是從一開始就是Object[]的數(shù)組是不能轉(zhuǎn)成MyObject[],這樣做會拋出ClassCastException異常,這是因為這個數(shù)組是用new Object[length]創(chuàng)建的,Java數(shù)組在創(chuàng)建的時候回記住每個元素的類型,就是在new的時候的類型。

  • 那么怎樣我們才可以強轉(zhuǎn)呢?看如下代碼

    private static Object goodCopyOf(Object arr, int newLength) {
      Class cls = arr.getClass();
      if (!cls.isArray()) {
          return null;
      }
      Object newArray = Array.newInstance(cls.getComponentType(), newLength);
      System.arraycopy(arr,0,newArray,0,Math.min(Array.getLength(arr), newLength));
      return newArray;
    }
    

    看了上面代碼,有的小伙伴會有疑問,為什么要用object接收數(shù)組對象,這是因為基本數(shù)據(jù)類型的數(shù)組不能傳給對象數(shù)組,但是可以轉(zhuǎn)成對象

    double[] arr = {1.1, 1.2, 1.4, 12.2};
    arr = (double[]) goodCopyOf(arr, 10);
    

訪問數(shù)組內(nèi)的對象

  • Array類提供了一些方法可以供我們使用
static Object get(Object array, int index) 返回指定位置的元素
static XXX getXXX(Object array, int index) XXX是基本類型,同上
static void set(Object array, int index, Object value) 設置指定位置的對象
static void setXXX(Object array, int index, XXX z) 設置指定位置的對象,XXX基本數(shù)據(jù)類型
static Object newInstance(Class<?> componentType, int length) 新建一個對象的數(shù)組。

以上來自Java SE *官方文檔 https://docs.oracle.com/javase/8/docs/api/

完整代碼如下

package io.ilss.reflection;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * className ArrayTest
 * description ArrayTest
 *
 * @author feng
 * @version 1.0
 * @date 2019-01-29 23:42
 */
public class ArrayTest {
    public static void main(String[] args) {
        double[] arr = {1.1, 1.2, 1.4, 12.2};
        arr = (double[]) goodCopyOf(arr, 10);
        System.out.println(Arrays.toString(arr));

        String[] arr1 = {"aa", "bb", "cc"};
        arr1 = (String[]) goodCopyOf(arr1, 10);
        System.out.println(Arrays.toString(arr1));

        System.out.println("ClassCastException");
        arr1 = (String[]) badCopyOf(arr1, 20);
    }

    private static Object[] badCopyOf(Object[] arr, int newLength) {
        Object[] newArray = new Object[newLength];
        System.arraycopy(arr, 0, newArray, 0, Math.min(arr.length, newLength));
        return newArray;
    }

    private static Object goodCopyOf(Object arr, int newLength) {
        Class cls = arr.getClass();
        if (!cls.isArray()) {
            return null;
        }
        Object newArray = Array.newInstance(cls.getComponentType(), newLength);
        System.arraycopy(arr, 0, newArray, 0, Math.min(Array.getLength(arr), newLength));
        return newArray;
    }
}

相關代碼的Github:https://github.com/imyiren/java-base-ilss

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容