一、動態語言
動態語言,是指程序在運行時可以改變其結構:新的函數可以引進,已有的函數可以被刪除等結構上的變化。比如常見的 JavaScript 就是動態語言,除此之外 Ruby,Python 等也屬於動態語言,而 C、C++則不屬於動態語言。從反射角度說 JAVA 屬於半動態語言。
反射機制概念 (運行狀態中知道類所有的屬性和方法)

在 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 對象、調用對象方法)
- 獲取想要操作的類的 Class 對象,他是反射的核心,通過 Class 對象我們可以任意調用類的方法。
- 調用 Class 類中的方法,既就是反射的使用階段。
- 使用反射 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
