Java的反射學習

  • Class類的使用

1.在面向對象的世界里洪燥,萬事萬物皆對象類是(哪個類的對象呢)誰的對象呢?
類是java.lang.Class類的實例對象
2.怎么表示Class類的實例對象呢稚疹?

public class ClassDemo1{
public static void main(String[] args){
  //Foo的實例對象如何表示
  Foo foo1 = new Foo();//foo1就表示出來了
  //Foo這個類 也是一個實例對象,是Class類的實例對象,如何表示呢钾恢?
  //任何一個類都是Class的實例對象翘鸭,這個實例對象有三種表示方式
  //第一種表示方式--->實際在告訴我們任何一個類都有一個隱含的靜態(tài)成員變量class
  Class c1 = Foo.class;
  //第二種表達方式 已知該類的對象通過getClass方法
  Class c2 = foo1.getClass();
  //第三種表達方式
  Class c3 = null;
  try{
      c3 = Class.forName("com.imooc.reflect.Foo");//(參數為全稱即包名)
  }catch(ClassNotFoundException e){
      e.printStackTrace();
  }
//c1,c2,c3表示了Foo類的類類型(class type)
//表示Foo類本身就是Class類的實例對象滴铅,這個對象我們稱之為該類的類類型
//c1,c2,c3都代表了Foo類的類類型就乓,一個類只可能是Class的一個實例對象汉匙,所以他們都是相等的
//我們完全可以通過類的類類型創(chuàng)建該類的對象實例--->通過c1 or c2 or c3 創(chuàng)建Foo的實例
  try{
      Foo foo = (Foo)c1.newInstance();//前提是要有無參數的構造方法
      foo.print();//調用foo類的print方法
  }catch{InstantiationException e}{
      e.printStackTrace();
    }
  }
}
 class Foo{
   void print(){
      System.out.printIn("foo");
   }
 }

3.Class類動態(tài)加載類的用法
首先學會區(qū)分什么是動態(tài)加載,什么是靜態(tài)加載

Class.forName("類的全稱")
- 不僅表示了類的類類型生蚁,還代表了動態(tài)加載類
- 請大家區(qū)分編譯噩翠,運行
- 編譯時刻加載類是靜態(tài)加載類,運行時刻加載類是動態(tài)加載類
  new 創(chuàng)建對象是靜態(tài)加載類邦投,在編譯時刻就需要加載所有的可能使用到的類
  靜態(tài)加載的弊端是伤锚,類名一旦更改,我們之前編寫的程序中所有用到該類名的地方都要修改志衣,這樣的程序耦合性很高屯援,擴展性就很差.

那么聰明的人就想到了一個辦法,就是動態(tài)加載蠢涝。用一個抽象的雷鳴代替具體的類名玄呛,或者一個統一的接口代替具體的方法,這樣一來程序運行的時候就在加載相應的類或接口即可和二。
擴展的功能(新功能就代表一個新類)只要implement這個類即可實現功能的擴展徘铝。
try{
    //動態(tài)加載類,在運行時刻加載
    Class c = Class.forName(args[0]);    
    //通過類類型惯吕,創(chuàng)建該類的對象
    OfficeAble oa=c.newInstance();//OfficeAble定義的功能類型接口
    oa.start();
}catch(Exception e){
    e.printStackTrace();
}

4.基本的數據類型 void關鍵字 都存在類類型

Class c1 = int.class;
Class c2 = String.class;
Class c3 = double.class;
Class c4 = Double.class;
Class c5 = void.class;

System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c2.getSimpleName());//不包含包名的類的名稱
System.out.println(c5.getName());

5.Class類的基本API操作
//可以獲取任意一個類的全部信息

publicclass ClassUtil{
/**
  *打印類的信息惕它,獲取類的成員函數
  *@param obj 該對象所屬類的信息
   public static void printClassMethodMessage(Object obj){
   //要獲取類的信息 首先要獲取類的類類型
    Class c = obj.getClass();//傳遞的是哪個子類的對象 c就是該子類的類類型
    //獲取類的名稱
    System.out.println("類的名稱是:"+c.getName());
    /*
     *Method類,方法對象
     *一個成員方法就是一個Method對象
     *getMethods()方法獲取的所有的public的函數废登,包括父類繼承而來的
     *getDeclaredMethods()獲取的是所有該類自己聲明的方法淹魄,不問訪問權限
     */
    Method[]ms = c.getMethods();//c.getDeclaredMethods()
    for(int i = 0; i < ms.length;i++){
        //得到方法的返回值類型的類類型
        Class returnType = ms[i].getReturnType();
        System.out.print(returnType.getName()+ " ");
        //得到方法的名稱
        System.out.print(ms[i].getName()+"(");
        //獲取參數類型-->得到的是參數列表類型的類類型
        Class[] paramTypes = ms[i].getParameterTypes();
        for(Class class1:paramTypes){
            System.out.print(class1.getName()+",")
        }
    System.out.println(")");
   
   }
  }


/**
  *打印類的信息,獲取類的成員變量
  *@param obj 改對象所屬類的信息
  */
public static void printFieldMessage(Object obj){
    Class c = obj.getClass();
    /*
     *成員變量也是對象
     *java.lang.reflect.Field
     *Filed類封裝了關于成員變量的操作
     *getFields()方法獲取的是所有的public的成員變量的信息
     *getDeclaredFields獲取的是該類自己聲明的成員變量的信息
    //Field[]fs = c.getFields();
    Field[] fs = c.getDeclaredFields();
    for(Field field : fs){
        //得到成員變量的類型的類類型
        Class fieldType = field.getType();
        String typeName = fieldType.getName();
        //得到成員變量的名稱
        String fieldName = field.getName();     
        System.out.println(typeName+" " + fieldName);
    }
}       
   /**
     *打印對象的構造函數的信息
     *@param obj
     */
    public static void printConMessage(Object obj){
        Class c = obj.getClass();
        /*
         *構造函數也是對象
         *java.lang.Constructor中封裝了構造函數的信息
         *getConstructors獲取所有的public的構造函數
         *getDeclaredConstructors();得到所有的構造函數
        */
        //Constructor[] cs = c.getConstructors();
        Constructor[] cs = c.getDeclaredConstructors();
        for(Constructor constructor : cs){
            System.out.println(constructor.getName()+"(");
            //獲取構造函數的參數列表-->得到的是參數列表的類類型
            Class[] paramTypes = constructor.getParameterTypes();
            for(Class class1 : paramTypes){
                 System.out.print(class1.getName()+",");
            }
        System.out.println(")");
        }
    }
}
  • 方法的反射
    1.如何獲取某個方法
    方法的名稱和方法參數列表才能唯一決定某個方法
    2.方法反射的操作
    method.invoke(對象堡距,參數列表)

    public class MethodDemo1{
        public static void main(String[] args){
            //要獲取print(int,int)方法
            //1.首先要獲取類的信息甲锡,獲取類的信息就要先獲取類的類類型      
            A a1 = new A();
            Class c = a1.getClass();
             /*
              *2.獲取方法 名稱和參數列表來決定
              *getMethod獲取的是public的方法包括繼承來的
              *getDelcaredMethod自己聲明的方法
              */
            try{
                //Method m =c.getMethod("print",new Class[]{int.class,int.class});
                Method m = c.getMethod("print",int.class,int.class);
                //方法的反射操作
                //a1.print(10,20);方法的反射操作是用m對象來進行方法調用和a1.print調用的效果完全相同
                //方法如果沒有返回值返回null,有返回值的返回具體的返回值需要強制轉換
                //Object o =m.invoke(a1,new Object[]{10,20});
                Object o = m.invoke(a1,10,20);
                System.out.println("=============");
                //獲取方法對象print(String,String)
                Method m1 = c.getMethod("print",String.class,String.class);
                //用方法進行反射操作
                //a1.print("hello","WORLD");
                o = m1.invoke(a1,"hello","WORLD");
                Syystem.out.println("=====無參函數====");
                //Method m2 = c.getMethod("print",new Class[]{});
                Method m2 = c.getMethod("print");
                //m2.invoke(a1,new Object[]{});
                m2.invoke(a1);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
     }
     class A{
        public void print(){
            System.out.println("helloworld");           
        }
        public void print(int a,int b){
            System.out.println(a+b);
        }
        public void print (String a,String b){
            System.out.println(a.toUpperCase()+","+b.toLowerCase());         
        }
    }
    
  • 成員變量的反射

  • 構造函數的反射

  • Java類加載機制

//參考視頻地址 http://www.imooc.com/video/3725
總結:反射可以進行動態(tài)加載,繞過編譯羽戒,提高了代碼的靈活性缤沦,在java的框架中應用較多。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末易稠,一起剝皮案震驚了整個濱河市缸废,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖企量,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件测萎,死亡現場離奇詭異,居然都是意外死亡届巩,警方通過查閱死者的電腦和手機硅瞧,發(fā)現死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恕汇,“玉大人零酪,你說我怎么就攤上這事∧床” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵孝凌,是天一觀的道長方咆。 經常有香客問我,道長蟀架,這世上最難降的妖魔是什么瓣赂? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮片拍,結果婚禮上煌集,老公的妹妹穿的比我還像新娘。我一直安慰自己捌省,他們只是感情好苫纤,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纲缓,像睡著了一般卷拘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上祝高,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天栗弟,我揣著相機與錄音,去河邊找鬼工闺。 笑死乍赫,一個胖子當著我的面吹牛,可吹牛的內容都是我干的陆蟆。 我是一名探鬼主播雷厂,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遍搞!你這毒婦竟也來了罗侯?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤溪猿,失蹤者是張志新(化名)和其女友劉穎钩杰,沒想到半個月后纫塌,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡讲弄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年措左,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片避除。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡怎披,死狀恐怖,靈堂內的尸體忽然破棺而出瓶摆,到底是詐尸還是另有隱情凉逛,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布群井,位于F島的核電站状飞,受9級特大地震影響,放射性物質發(fā)生泄漏书斜。R本人自食惡果不足惜诬辈,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荐吉。 院中可真熱鬧焙糟,春花似錦、人聲如沸样屠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痪欲。三九已至混巧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間勤揩,已是汗流浹背咧党。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留陨亡,地道東北人傍衡。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像负蠕,于是被迫代替她去往敵國和親蛙埂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內容

  • 多態(tài) 任何域的訪問操作都將有編譯器解析遮糖,如果某個方法是靜態(tài)的绣的,它的行為就不具有多態(tài)性 java默認對象的銷毀順序與...
    yueyue_projects閱讀 936評論 0 1
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法屡江,繼承相關的語法芭概,異常的語法,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • 1. 了解 Java 中的反射 1.1 什么是 Java 的反射 Java 反射是可以讓我們在運行時獲取類的函數惩嘉、...
    Ten_Minutes閱讀 530評論 0 4
  • 泛型 對象和實例是一個意思罢洲,類與對象的關系就像數據類型和變量一樣。 泛型的主要目的之一就是用來指定類(如:容器)要...
    yueyue_projects閱讀 569評論 0 0
  • 寫在前面的話 最近高產似母豬文黎,每天都會寫點關于這個系列的總結惹苗。周一了,又開始忙碌的一天耸峭。項目趕趕趕桩蓉,bug改改改,...
    nick_young閱讀 1,718評論 0 2