今天來學習一下Java的反射機制,若有不當請多指教!學習
反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。code
Java中的反射主要和Class
類有關。Class類沒有公共構造方法。Class 對象是在加載類時由 Java 虛擬機以及經過調用類加載器中的defineClass方法自動構造的。也就是說不須要咱們本身去處理建立,JVM已經幫咱們建立好了。對象
一、getClass()
getClass()是Object類中的方法,也就是說每一個類都有本身的Class對象。字符串
Student s1 = new Student();//這一new 產生一個Student對象,一個Class對象。 Class stuClass1 = s1.getClass();
二、.class
任何數據類型(包括基本數據類型)都有一個「靜態」的class屬性,好比String.Classget
Class stuClass2 = Student.class;
三、Class.forName(String className) —— 推薦
經過Class類的靜態方法forName獲取Class對象(經常使用)編譯器
Class stuClass3 = Class.forName("czy.Student");//注意此字符串必須是真實路徑→包名.類名
注意:在運行期間,一個類,只有一個Class對象產生。虛擬機
public class Constructors { public static void main(String[] args) throws Exception { //1.加載Class對象 Class c = Class.forName("czy.Student"); //2.獲取全部公有構造方法 Constructor[] conArray = c.getConstructors(); //三、獲取全部的構造方法(包括:私有、受保護、默認、公有) Constructor[] conArray = c.getDeclaredConstructors(); //四、獲取公有、無參的構造方法 Constructor con = c.getConstructor(); //由於是無參的構造方法因此類型是一個null,不寫也能夠:這裏須要的是一個參數的類型,切記是類型 //調用構造方法 Object obj = con.newInstance(); //五、獲取私有構造方法,並調用 con = c.getDeclaredConstructor(char.class); //調用構造方法 con.setAccessible(true);//暴力訪問(忽略掉訪問修飾符) obj = con.newInstance('男'); } }
public class Fields { public static void main(String[] args) throws Exception { //一、獲取Class對象 Class stuClass = Class.forName("czy.Student"); //二、獲取全部公有的字段 Field[] fieldArray = stuClass.getFields(); //三、獲取全部的字段(包括私有、受保護、默認的) Field[] fieldArray = stuClass.getDeclaredFields(); //四、獲取公有字段"name"並調用 Field f = stuClass.getField("name"); //獲取一個對象 Object obj = stuClass.getConstructor().newInstance();//產生Student對象--》Student student = new Student(); //爲字段設置值 f.set(obj, "劉德華");//爲Student對象中的name屬性賦值--》student.name = "劉德華" //五、獲取私有字段"phone"並調用 f = stuClass.getDeclaredField("phone"); f.setAccessible(true);//暴力反射,解除私有限定 f.set(obj, "13415038974"); } }
public class MethodClass { public static void main(String[] args) throws Exception { //1.獲取Class對象 Class stuClass = Class.forName("czy.Student"); //2.獲取全部公有方法 Method[] methodArray = stuClass.getMethods(); //3.獲取全部的方法,包括私有的 Method[] methodArray = stuClass.getDeclaredMethods(); //4.獲取公有的show1()方法 Method m = stuClass.getMethod("show1", String.class); //調用show1()方法 Object obj = stuClass.getConstructor().newInstance(); m.invoke(obj, "劉德華"); //5.獲取私有的show4()方法 m = stuClass.getDeclaredMethod("show4", int.class); m.setAccessible(true);//解除私有限定 Object result = m.invoke(obj, 20);//須要兩個參數,一個是要調用的對象(由反射獲取),一個是實參 } }
例如:有一個String泛型的集合,怎樣能向這個集合中添加一個Integer類型的值?io
public class Demo { public static void main(String[] args) throws Exception{ ArrayList<String> strList = new ArrayList<>(); strList.add("aaa"); strList.add("bbb"); //獲取ArrayList的Class對象,反向的調用add()方法,添加數據 Class intClass = strList.getClass(); //獲得 strList 對象的字節碼 對象 //獲取add()方法 Method m = intClass.getMethod("add", Object.class); //調用add()方法 m.invoke(strList, 100); } }
固然這樣只能躲過編譯器檢查,去遍歷的話仍是會拋出異常的。編譯