javaSE (四十一)反射的概念、通過反射越過泛型檢查
阿新 • • 發佈:2018-12-16
作為javaSE的最後一篇,反射更多的是一種程式設計理念或者說優化,對前面的java多型的一種優化,簡單但是需要理解一下
這篇文章寫的很好:
大白話說Java反射:入門、使用、原理
1、反射的概念:
- 反射是相對於正射來說的,正射是先通過構造方法建立類的物件,然後使用類的各種屬性和方法
- 而反射是什麼時候想要用到這個類了,就通過類名把這個類載入進來,然後獲得構造方法,獲得屬性和方法,更加地可持續
方法:
獲得類.class
大部分應用的是第一種,指導類名(完整的,包名+類名)可以和config配置檔案結合起來
下面寫一個程式碼包括以下的反射用法:
- 通過類名獲得類
- 通過無參構造獲得物件,需要從class向下轉型
- 指定有參建構函式 ,引數都是位元組碼
- 用這個有參構造物件
- 獲得欄位(私有private屬性)
- 去除私有許可權
- 修改欄位
- 獲得無參方法
- 獲得有參方法
例項程式碼:
package reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Reflection {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("reflection.Student");//1、通過類名獲得類
Student s = (Student) clazz.newInstance();//2、通過無參構造獲得物件,需要從class向下轉型
Constructor con = clazz.getConstructor(String.class,int.class); //3、指定有參建構函式,引數都是位元組碼
//T newInstance(Object... initargs)
Student str1 = (Student) con.newInstance("吳彥祖",23); //4、用這個有參構造物件
//Field field = clazz.getField("name");//5、獲得欄位(共有public屬性)
Field field = clazz.getDeclaredField("name");//5、獲得欄位(私有private屬性)
field.setAccessible(true); //6、去除私有許可權
field.set(str1, "PziAn"); //7、修改欄位
System.out.println(str1); //輸出:Student [name=PziAn, age=23]
//方法 getMethod(String name, 類<?>... parameterTypes)
Method method1 = clazz.getMethod("eat"); //8、獲得無參方法
method1.invoke(str1); //輸出:吃魷魚絲!
Method method2 = clazz.getMethod("eat",int.class); //9、獲得有參方法
method2.invoke(str1,8); //輸出:吃魷魚絲8次!
}
}
輸出:
Student [name=PziAn, age=23]
吃魷魚絲
吃魷魚絲8次!
2、通過反射越過泛型檢查:
泛型只是在編譯階段起作用,執行階段會被擦除,所以我們在編譯後拿到這個類的位元組碼,可以做一些事情,比如在ArrayList<Integer> 中放String型別的數
編譯:將檔案.java變成機器能識別的位元組碼.class
例項程式碼:
package reflection;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class ArrayListwithreflection {
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<>();
list.add(111);
list.add(222);
Class clazz = Class.forName("java.util.ArrayList");
// 獲得add方法
Method method = clazz.getMethod("add", Object.class);// 注意這裡是object
method.invoke(list, "南京是一座很美的城市!");
System.out.println(list);
}
}
輸出:
[111, 222, 南京是一座很美的城市!]