JAVA基礎——反射詳解

1.什麼是反射( reflect

JAVA反射機制是運行狀態中,對於任意一個類都能夠知道這個類的所有屬性個方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取信息及動態調用對象的方法的功能稱爲java語言的反射機制。

簡單說:在運行狀態下,通過class文件對象,去使用構造方法,成員變量和成員方法

注意:在反射中包含Declared的方法表示獲取私有的成員內容,一般結合setAccessible(true)方法一起使用

2.創建Class文件的三種方式

Class.forName("類全名");

對象名.getClass(); 

類名.class

推薦使用:Class.forName("類全名");

3.獲取構造方法並創建對象

概述:
       java.lang.reflect.Constructor:構造方法管理器,通過該對象的newInstance方法能有創建構造方法
步驟
1、獲取Class對象
2、通過調用getDeclaredConstructor或者getConstructor 方法創建構造器(Constructor)對象,如果構造方法沒有形式參數寫null
      public Constructor  getDeclaredConstructor(形式參數1對應的.class對象, 形式參數2對應的.class對象....):該方法可以獲取私有構造方法
      public Constructor  getConstructor(形式參數1對應的.class對象, 形式參數2對應的.class對象....):該方法不能獲取私有構造方法
3、如果獲取到的是私有的構造方法的構造器對象,需要調用構造器對象的setAccessible(true)方法
4、通過構造器對象的newInstance(實際參數1, 實際參數2)創建對象,如果沒有實際參數寫null

舉例
       1、通過private Person(String name, int age)創建對象
            Class clazz =   Class.forName("com.itcast.Person"); //必須通過類全名獲取
            Constructor con = clazz.get DeclaredConstructor(String.class, int.class);//形式參數列表對應的.class列表
                   con.setAccessible(true);//此處不設置,無法創建該對象,因爲構造方法是私有的
                   Object obj = con.newInstance("zhangsan",120); //調用newInstance(實際參數列表)創建對象

      2、通過public Person()創建對象
             Class clazz =   Class.forName("com.itcast.Person");//必須通過類全名獲取
            Constructor con = clazz.getDeclaredConstructor(null); //因爲沒有形式參數,所以寫null
             con.setAccessible(true);//此處不設置,無法創建該對象,因爲構造方法是私有的
                   Object obj = con.newInstance(); //因爲不需要實際參數,所以調用無參的newInstance方法

4.獲取屬性並調用

概述:
      java.lang.reflect.Field:屬性管理器對象,可以對該類的對象的屬性值進行修改和獲取

步驟
      1、獲取Class對象
      2、通過調用getDeclaredField("屬性名")或通過調用getField("屬性名")  獲取屬性管理器
      3、如果獲取的是私有的屬性,調用屬性管理器的 setAccessible(true)方法
      4、調用屬性管理器的set(該類的對象,值) 來設置屬性值
           調用屬性管理器的get(該類的對象)來獲取屬性值

舉例
            Person p1 = new Person();
                   Person p2= new Person(); 
                   Class clazz =   Class.forName("Person"); //第一步獲取Class對象  
                   Field field = clazz.getDeclaredField("name"); 
    //第二步通過調用getDeclaredField("屬性名")或通過調用getField("屬性名")  獲取屬性管理器  
                   field.setAccessible(true); //第三步如果獲取的是私有的屬性,調用屬性管理器的setAccessible(true)方法  
                   field.set(p1, "張三"); //第四步用屬性管理器的set(該類的對象,值) 來設置屬性值
                   field.set(p2, "李四");
                   
                   System.out.println(field.get(p1)); //第四步調用屬性管理器的get(該類的對象)來獲取屬性值  
                   System.out.println(field.get(p2));

5.獲取成員方法並調用

概述:
       java.lang.reflect.Method:方法管理器,可以執行該類的對象的方法

步驟
      1、獲取Class對象
      2、通過調用getDeclaredMethod("方法名",形式參數1.class, 形式參數2.class..)或通過調用geMethod("方法名",形式參數1.class, 形式參數2.class..)  獲取屬性管理器,如果沒有形式參數寫null
      3、如果獲取的是私有的方法,調用方法管理器的 setAccessible(true)方法
      4、通過屬性管理器的invoke(該類的對象,實際參數)來執行方法,如果沒有實際參數寫null

案例
              Person p1 = new Person("張三",13); 
                   Person p2= new Person("李四",14); 
                   Class clazz =   Class.forName("Person"); 
                   
                   /* 
                   * 調用setName方法 
                   */ 
                   Method setName = clazz.getDeclaredMethod("setName", String.class); 
                   setName.setAccessible(true); //如果getName方法是私有的,此處必須寫  
                   setName.invoke(p1, "張三改"); 
                   
                   /* 
                   * 調用getName方法 
                   */ 
                   Method getName = clazz.getDeclaredMethod("getName", null); //獲取Person類的getName方法對應的方法管
                   getName.setAccessible(true); //如果getName方法是私有的,此處必須寫
                   Object object = getName.invoke(p1, null); //執行p1對象的getName方法,並且將返回值賦值給object
                   System.out.println(object); 

6.反射練習

1:通過反射修改成員變量的值,包括私有
2: 通過反射運行配置文件
   在JAVA項目下新建配置文件config,內容爲: class=Person name=jack
JAVA代碼:
              Properties p = new Properties(); 
                   p.load(new FileReader("config")); 
                   String className   = (String)p.get("class"); 
                   String name = (String)p.get("name"); 
                   
                   Class clazz = Class.forName(className); 
                   //創建對象 
                   Constructor constructor = clazz.getConstructor(null); 
                   Object instance = constructor.newInstance(); 
                   
                   //通過setName設置name屬性 
                   Method setName = clazz.getDeclaredMethod("setName", String.class); 
                   setName.invoke(instance,name ); 
                   
                   //通過getName設置name屬性 
                   Method method = clazz.getDeclaredMethod("getName",null); 
                   Object object = method.invoke(instance, null); 
                   System.out.println(object);

3: 通過反射給 ArrayList<Integer>中添加String 類型的數據
                ArrayList list = new ArrayList(); 
                   list.add(123); 
                   
                   
               Class clazz =   Class.forName("java.util.ArrayList");//必須通過類全名獲取 
               Method method = clazz.getDeclaredMethod("add", Object.class); 
               method.setAccessible(true); 
               method.invoke(list, "ss"); 
               
               for(Object obj: list){ 
                       System.out.println(obj); 
               } 


 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章