java基礎——反射與回調

一、java的反射

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

   調用對象的方法的功能成爲java語言的反射機制。

   java的反射機制主要提供了以下功能:

    • 在運行時判斷任意一個對象所屬的類;

    • 在運行時構造任意一個類的對象;

    • 在運行時判斷任意一個類所具有的成員變量和方法;

       • 在運行時調用任意一個對象的方法;

    • 生成動態代理。

  1、JVM創建Class類對象的過程

                                         

  2、獲取class的三種方式

  1. Class.forName(“com.weige.Test”);
  2. Test.class;
  3. new Test().getClass();

                      

  3、反射的作用

    Java中編譯類型有兩種

      靜態編譯:在編譯時確定類型,綁定對象即通過
      動態編譯:運行時確定類型,綁定對象
    反射允許靜態語言在運行時檢查、修改程序的結構與行爲。 在靜態語言中,使用一個變量時,必須知道它的類型;在Java中,變量的類型信息在編譯時都保存到了class文件中,這樣在運行時才能保證準確無誤。換句話說,程序在運行時的行爲都是固定的。如果想在運行時改變,就需要Java的反射機制。

    動態編譯最大限度地發揮了Java的靈活性,體現了多態的應用,可以減低類之間的耦合性。 Java反射是Java被視爲動態(或準動態)語言的一個關鍵性質。

 

  4、反射的應用場景

  •     最重要的用途就是開發各種通用框架,注入屬性,調用方法,如Spring
  •     JDBC中,利用反射動態加載了數據庫驅動程序
  •     Web服務器中利用反射調用了Sevlet的服務方法
  •     Eclispe等開發工具利用反射動態刨析對象的類型與結構,動態提示對象的屬性和方法 

      

  5、反射機制的優缺點?

  • 優點:可以動態執行,在運行期間根據業務功能動態執行方法、訪問屬性,最大限度發揮了java的靈活性。
  • 缺點:對性能有影響,這類操作總是慢於直接執行java代碼。

  

  A、反射實例——通過屬性調用對象

public static void main(String[] args) throws Exception{
        Class<?> a = new Test().getClass();
        Test test = new Test("456");
        Field field= a.getDeclaredField("age");
        field.set(test, "123");
        System.out.println(field.get(test));
    }

  B、反射實例——通過方法調用對象

public static void main(String[] args) throws Exception{
        Class<?> a = new Test().getClass();
        Method method = a.getDeclaredMethod("say", String.class,int.class);
        method.invoke(a.newInstance(), "asd",1);
    }
    
private static void say(String a,int b) {
        System.out.println("測試"+a+b);
    }

 

二、函數的回調

    在Java裏面,我們使用接口來實現回調。回調函數,或簡稱回調,是指通過函數參數傳遞到其它代碼的,某一塊可執行代碼的引用。這一設計允許了底層代碼調用在高層定義的子程序。

  程序員A寫了一段程序(程序a),其中預留有回調函數接口,並封裝好了該程序。程序員B要讓a調用自己的程序b中的一個方法,於是,他通過a中的接口回調自己b中的方法。目的達到。在C/C++中,要用回調函數,被掉函數需要告訴調用者自己的指針地址,但在JAVA中沒有指針,怎麼辦?我們可以通過接口(interface)來實現定義回調函數。

  假設我是程序員A,以下是我的程序a:

public class Caller  
{  
    public MyCallInterface mc;  
  
    public void setCallfuc(MyCallInterface mc)  
    {  
       this.mc= mc;  
    }  
  
    public void call(){  
       this.mc.method();  
    }  
}      

我還需要定義一個接口,以便程序員B根據我的定義編寫程序實現接口。

public interface MyCallInterface  
{  
    public void method();  
  
}  

於是,程序員B只需要實現這個接口就能達到回調的目的了:

public class B implements MyCallInterface  
{  
    public void method()  
    {  
       System.out.println("回調");  
    }  
  
    public static void main(String args[])  
    {  
       Caller call = new Caller();  
       call.setCallfuc(new B());  
       call.call();  
    }  
}  

 

  主要就是回調者需要實現一個回調接口,然後把自己,也就是相當於接口當做參數傳給別人,別人拿到這個接口之後,最終都會調用接口中的方法,就相當於執行了回調方法。   

    下面舉個通俗的例子:
    某天,我打電話向你請教問題,當然是個難題你一時想不出解決方法,我又不能拿着電話在那裏傻等,於是我們約定:等你想出辦法後打手機通知我,這樣,我就掛掉電話辦其它事情去了。過了XX分鐘,我的手機響了,你興高采烈的說問題已經搞定,應該如此這般處理。故事到此結束。這個例子說明了“異步+回調”的編程模式。其中,你後來打手機告訴我結果便是一個“回調”過程;我的手機號碼必須在以前告訴你,這便是註冊回調函數;我的手機號碼應該有效並且手機能夠接收到你的呼叫,這是回調函數必須符合接口規範。

 

 

參考:

https://blog.csdn.net/qq_30346471/article/details/84299993

https://blog.csdn.net/weixin_45864705/article/details/126271798

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