SeventhDay--Java基礎(五)反射、內部類

反射:
 反射:在運行時動態分析或使用一個類進行工作。
 java.lang.Class類:描述類信息的類。
 類對象:描述一個類信息的對象,當虛擬機加載類的時候,就會創建這個類的類對象並加載該對象,Class是類對象的類型。
 
 獲得類對象的方式:
  用" 類名.class "獲得這個類的類對象。
  用類的對象掉用getClass(),如object.getClass()得到這個對象的類型的類對象。
  可以使用Class.forName(類名),也可以得到這個類的類對象,(注意,這裏寫的類名必須是全限定名(全名),是包名加類名,XXX.XXX.XXXX)。
  基本類型也有類對象,用" 封裝類.TYPE "可以獲得對應的基本類型的類對象。

 java.lang.reflect包下的三個重要類:
  Field屬性類:用來描述屬性的信息。
  Method方法類:方法的信息的描述。
  Constructor構造方法類:用來描述構造方法的信息。

 Class類中的常用方法:
  newInstance()
   創建此 Class 對象所表示的類的一個新實例(調用無參構造創建的對象)。
  getDeclaredMethods()
   獲得的是一個Method方法類對象的數組,獲得本類(不包括父類)聲明的所有(包括private的)方法對象。
  getMethods()     //推薦使用
   獲得的是一個Method方法類對象的數組,獲得所有(父類的也包括)publice的方法對象。
  getDeclaredConstructors()
   獲得的是一個Constructor構造方法類對象的數組,獲得這個類聲明的所有構造方法對象。
  getConstructors()    //推薦使用
   獲得的是一個Constructor構造方法類對象的數組,獲得所有publice的構造方法對象。
  getDeclaredFields()    //推薦使用
   獲得的是一個Field屬性類對象的數組,獲得本類聲明的所有屬性的屬性對象。
  getFields()
   獲得的是一個Field屬性類對象的數組,獲得所有publice的屬性對象。
   
 使用反射構造一個類的對象的步驟:
  a. 獲得類對象
  b. 獲得構造方法對象
  c. 獲得對象,用構造方法對象調用構造方法,如果使用無參構造方法,可以跳過第二步,直接使用" 類對象.newInstance() "方法來獲得這個類的對象
  d. 獲得方法對象
  e. 用方法對象調用方法(用這個類的對象作爲第一參數)
  如下面的例子:
   反射機制的實現類:
    package day07.reflect;    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;   
    public class TestReflect {     
     public static Object get(String className , Map<String,Object> map) throws Exception{
      Class c = Class.forName(className);                  //獲得類對象
      Object o = c.newInstance();                   //獲得對象
      Set<String> set = map.keySet();
      for(String str : set){
       String s = "set" + str.substring(0,1).toUpperCase()+str.substring(1);
       Field f = c.getDeclaredField(str);
       Method m = c.getMethod(s, f.getType());        //獲得方法對象
       m.invoke(o, map.get(str));                       //用方法對象調用方法
      }
      return o;
     }
     
     public static void main(String[] args) throws Exception { 
      Map m = new HashMap();
      m.put("name", "zhang");
      m.put("age", 22);
      Object o = get("day07.reflect.Student",m);
      Student s = (Student) o;
      System.out.println(s.getName() + "   " + s.getAge());
      
      Map m1 = new HashMap();
      m1.put("name", "li");
      m1.put("gender", "男");
      Object o1 = get("day07.reflect.Teacher",m1);
      Teacher t = (Teacher) o1;
      System.out.println(t.getName() + "    " + t.getGender());
     }
    }
   學生類:
    package day07.reflect;    
    public class Student {
     private String name;    
     private int age;    
     public int getAge() {
      return age;
     }    
     public void setAge(int age) {
      this.age = age;
     }    
     public String getName() {
      return name;
     }    
     public void setName(String name) {
      this.name = name;
     }
    } 
   教師類:
    package day07.reflect;    
    public class Teacher {
     private String name;    
     private String gender;    
     public String getGender() {
      return gender;
     }    
     public void setGender(String gender) {
      this.gender = gender;
     }      
     public String getName() {
      return name;
     }    
     public void setName(String name) {
      this.name = name;
     }    
    }
 
內部類:
 定義:
  定義在另外一個類中的類,就是內部類。
  編譯後生成的兩個獨立的類:Outer.class 和Outer$Inner.class。
  
 內部類的分類:
  靜態內部類:靜態內部類定義在類中,任何方法外,用static修飾
   靜態內部類只能訪問外部類的靜態成員。
   在外部類的外部,要創建一個靜態內部類對象不需要外部類對象:
    Outer.Inner in = new Outer.Inner();
   在本類內部生成內部類對象的方式:
    Inner in = new Inner(); 
 
  成員內部類:作爲外部類的一個成員存在,與外部類的屬性、方法並列
   在內部類中可以直接訪問外部類的私有屬性。
   內部類和外部類的實例變量允許命名衝突。
    在內部類中訪問實例變量:this.屬性
    在內部類訪問外部類的實例變量:外部類名.this.屬性
   在外部類的外部,要創建一個成員內部類對象,要首先建立一個外部類對象,然後再創建一個成員內部類對象。
    Outer out = new Outer();
    Outer.Inner in = out.new Inner();
   在本類內部生成內部類對象的方式:
    在靜態方法中:Inner in = new Outer().new Inner();
    在非靜態方法中:Inner in = this.new Inner();
   成員內部類不可以有靜態成員,這是因爲靜態屬性是在加載類的時候創建,這個時候內部類還沒有被創建。
    
  局部內部類:在外部類的方法中定義的內部類
   與局部變量類似,在局部內部類前不可以加修飾符public和private,其作用域爲定義它的代碼塊。
   局部內部類不僅可以訪問外部類的實例變量,還可以訪問外部類的局部變量,但要求外部類的局部變量必須爲final的。
   配合接口使用,來做到強制弱耦合。
   在外部類的外部不可創建局部內部類對象,只能在局部內部類所在的方法中創建:
    Inner in = new Inner();
   
  匿名內部類:一種特殊的局部內部類
   沒有名字,也沒有class、extends、implements關鍵字
   用一種隱含的方式實現一個接口或繼承一個類,並且只能創建一次實例。
   實現方式:在某個語句中,new 父類/父接口名字(){ 類體中實現方法 }
    例如:
     TreesSet ts = new TreeSet(new Comparator(){
      public int compare(Object o1, Object o2){
       return 0;
      }
     });
   匿名內部類屬於局部內部類,那麼局部內部類的所有限制都對其生效。
   匿名內部類是唯一一種無構造方法的類,因爲構造器的名字必須合類名相同,而匿名內部類沒有類名。

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