Java基礎(三)反射的使用


一、動態語言

動態語言,是指程序在運行時可以改變其結構:新的函數可以引進,已有的函數可以被刪除等結構上的變化。比如常見的 JavaScript 就是動態語言,除此之外 Ruby,Python 等也屬於動態語言,而 C、C++則不屬於動態語言。從反射角度說 JAVA 屬於半動態語言。

反射機制概念 (運行狀態中知道類所有的屬性和方法)

image

在 Java 中的反射機制是指在運行狀態中,對於任意一個類都能夠知道這個類所有的屬性和方法;並且對於任意一個對象,都能夠調用它的任意一個方法;這種動態獲取信息以及動態調用對象方法的功能稱為 Java 語言的反射機制(但他不能動態的增刪方法屬性,要想修改方法需要實現Invokehandler接口,重寫invoke方法)。

二、反射的應用場合

1、編譯時類型和運行時類型

在 Java 程序中許多對象在運行時都會出現兩種類型:編譯時類型和運行時類型。** 編譯時的類型由聲明對象時實用的類型來決定,運行時的類型由實際賦值給對象的類型決定** 。如:

Person p = new Student();

其中編譯時類型為 Person,運行時類型為 Student。

2、編譯時類型無法獲取具體方法

程序在運行時還可能接收到外部傳入的對象,該對象的編譯時類型為 Object,但是程序有需要調用該對象的運行時類型的方法。為了解決這些問題,程序需要在運行時發現對象和類的真實信息。然而,如果編譯時根本無法預知該對象和類屬於哪些類,程序只能依靠運行時信息來發現該對象和類的真實信息,此時就必須使用到反射了。

三、Java 反射 API

反射 API 用來生成 JVM 中的類、接口或者對象的信息。

  • Class 類:反射的核心類,可以獲取類的屬性,方法等信息。
  • Field 類:Java.lang.reflect 包中的類,表示類的成員變量,可以用來獲取和設置類之中的屬性值。
  • Method 類: Java.lang.reflect 包中的類,表示類的方法,它可以用來獲取類中的方法信息或者執行方法。
  • Constructor 類: Java.lang.reflect 包中的類,表示類的構造方法。

四、反射使用步驟(獲取 Class 對象、調用對象方法)

  1. 獲取想要操作的類的 Class 對象,他是反射的核心,通過 Class 對象我們可以任意調用類的方法。
  2. 調用 Class 類中的方法,既就是反射的使用階段。
  3. 使用反射 API 來操作這些信息。

1、獲取 Class 對象的 3 種方法1、獲取 Class 對象的 3 種方法

(1)調用某個對象的 getClass() 方法;調用某個對象的 getClass() 方法;
Person p = new Person();
Class clazz = p.getClass();
(2)調用某個類的 class 屬性來獲取該類對應的 Class 對象;(2)調用某個類的 class 屬性來獲取該類對應的 Class 對象;

Class clazz = Person.class;

(3)使用 Class 類中的 forName() 靜態方法 ( 最安全 / 性能最好);(3)使用 Class 類中的 forName() 靜態方法 ( 最安全 / 性能最好);

Class clazz = Class.forName("類的全路徑"); (最常用)

2、創建對象的兩種方法2、創建對象的兩種方法

  • Class 對象的 newInstance(),使用 Class 對象的 newInstance()方法來創建該 Class 對象對應類的實例,但是這種方法要求該 Class 對象對應的類有默認的空構造器。
  • 調用 Constructor 對象的 newInstance(),先使用 Class 對象獲取指定的 Constructor 對象,再調用 Constructor 對象的 newInstance()方法來創建 Class 對象對應類的實例,通過這種方法可以選定構造方法創建實例。
//獲取 Person 類的 Class 對象
Class clazz = Class.forName("reflection.Person");
//使用.newInstane 方法創建對象
Person p = (Person) clazz.newInstance();
//獲取構造方法並創建對象
Constructor c = clazz.getDeclaredConstructor(String.class,String.class,int.class);
//創建對象並設置屬性
Person p1 = (Person) c.newInstance("李四","男",20);

五、實例

首先,上代碼:

public class Test1 {
    /**
     * 二分查找   O(logN)
     * @param arr
     * @param target
     * @return
     */
    private int binarySearch(int[] arr,int target) {
        if(arr == null || arr.length == 0) {
            return -1;
        }
        int left = 0;
        int right = arr.length-1;
        while (left <= right) {
            int mid = left+(right-left)>>1;
            if(arr[mid] == target) {
                return mid;
            }
            if(arr[mid] > target) {
                right = mid-1;
            }else {
                left = mid+1;
            }
        }
        return -1;
    }

    /**
     * 尋找最大值 O(N)
     * @param arr
     * @return
     */
    private int findMax(int[] arr) {
        if(arr == null || arr.length == 0) {
            return -1;
        }
        int maxValue = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i] > maxValue) {
                maxValue = arr[i];
            }
        }
        return maxValue;
    }

    /**
     * 歸並排序 O(N㏒N)
     * @param arr
     */
    private void mergeSort(int[] arr) {
        if(arr == null || arr.length == 0) {
            return;
        }
        for(int i = 1;i < arr.length;i = i*2) {
            sortCode(arr,i);
        }
        System.out.println(Arrays.toString(arr));
    }

    private void sortCode(int[] arr, int gap) {
        int s1 = 0;
        int e1 = s1+gap-1;
        int s2 = e1+1;
        int e2 = s2+gap-1 > arr.length-1 ? arr.length-1 : s2+gap-1;

        int[] temp = new int[arr.length];
        int index = 0;

        while (s2 < arr.length) {
            while (s1 <= e1 && s2 <= e2) {
                if(arr[s1] < arr[s2]) {
                    temp[index++] = arr[s1++];
                }else {
                    temp[index++] = arr[s2++];
                }
            }

            while (s1 <= e1) {
                temp[index++] = arr[s1++];
            }

            while (s2 <= e2) {
                temp[index++] = arr[s2++];
            }

            s1 = e2+1;
            e1 = s1+gap-1;
            s2 = e1+1;
            e2 = s2+gap-1 > arr.length-1 ? arr.length-1 : s2+gap-1;
        }

        while (s1 < arr.length) {
            temp[index++] = arr[s1++];
        }
        System.arraycopy(temp,0,arr,0,arr.length);
    }
}

然后反射傳參調用,並獲取結果:

public class Test {
    public static void main(String[] args) {
        int[] array = {1,58,69,21,47,35,26,71,19};
        Test1 test1 = new Test1();
        Class<? extends Test1> c = test1.getClass();
        try {
            System.out.println("數組:"+Arrays.toString(array));

            //找最大值
            Method method1 = c.getDeclaredMethod("findMax",int[].class);
            method1.setAccessible(true);
            Object o = method1.invoke(test1, new Object[]{array});
            System.out.println("最大值是:"+o.toString());

            //排序
            Method method2 = c.getDeclaredMethod("mergeSort",int[].class);
            method2.setAccessible(true);
            method2.invoke(test1,new Object[]{array});
            System.out.println("歸並排序后:"+Arrays.toString(array));

            //二分查找
            Method method3 = c.getDeclaredMethod("binarySearch",int[].class,int.class);
            method3.setAccessible(true);
            Object o1 = method3.invoke(test1, new Object[]{array,35});
            System.out.println("二分查找:"+o1.toString());

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}

運行結果:

數組:[1, 58, 69, 21, 47, 35, 26, 71, 19]
最大值是:71
[1, 19, 21, 26, 35, 47, 58, 69, 71]
歸並排序后:[1, 19, 21, 26, 35, 47, 58, 69, 71]
二分查找:4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM