Java的反射機(jī)制和 OC 對比

image.png

一 Java反射機(jī)制概述

我們都知道程序在運(yùn)行的時候要經(jīng)過編譯期和運(yùn)行期,編譯期就是編譯器吧源代碼翻譯成機(jī)器能識別的代碼,比如編譯器把Java代碼編譯成jvm識別的字節(jié)碼文件,而運(yùn)行期指的是將可執(zhí)行文件交給操作系統(tǒng)去執(zhí)行,JAVA反射機(jī)制就是在運(yùn)行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意個對象,都能夠調(diào)用他的任意方法和屬性;
這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為Java語言的反射機(jī)制

二 Java反射機(jī)制實(shí)現(xiàn)原理

Java語言編譯后會生成一個 .class文件,反射就是通過字節(jié)碼文件找到某一個類、類中的方法以及屬性。

反射的實(shí)現(xiàn)主要借助以下四個類:
Class: 類的對象
Constructor: 類的構(gòu)造方法
Filed: 類中的屬性對象
Method:類中的方法對象

1、獲取類對象:

通過類名獲取Class對象, Class<T> c = Class.forName("類的完全路徑");
通過CLass對象獲取具體的類對象: Object o = c.newInstance();

2、獲取類中的構(gòu)造方法
  • Constructor<T> getConstructor(Class<?>... parameterTypes)
    返回一個 Constructor對象,它反映此Class對象所表示的類的指定公共構(gòu)造方法
  • public Constructor<?>[] getConstructors()
    返回一個包含某些Constructor 對象的數(shù)組,這些對象反映此 Class 對象所表示的類的所有公共構(gòu)造方法
  • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
    返回一個 Constructor對象,該對象反映此Class對象所表示的類或接口的指定公共構(gòu)造方法
3、獲取類中的屬性
  • public native Field getDeclaredField(String name)
    返回一個 Filed 對象,該對象反映此Class對象所表示的類或接口的指定已聲明字段

  • public native Field[] getDeclaredFields()
    返回Filed 對象的一個數(shù)組,這些對象反映此Class對象所表示的類或接口的指定已聲明字段

  • public Field getField(String name)
    返回一個 Filed 對象,他反映此 Class 對象所表示的類或接口的指定公共成員字段。

  • public Field[] getFields()
    返回一個包含某些 Filed 對象的數(shù)組,這些對象反映此 Class 對象所標(biāo)識的類或接口的所有課方訪問的公共成員字段。

4、獲取類中的方法
  • public Method getMethod(String name, Class<?>... parameterTypes)
    返回一個 Method 對象,他反映此 Class對象所表示的類或者接口的指定公共成員方法

  • public Method[] getMethods()
    返回一個包含某些 Method 對象的數(shù)組,這些對象反映此 Class對象所表示的類或者接口的公共 member 方法。

  • public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
    返回一個 Method 對象,他反映此 Class對象所表示的類或者接口的指定已聲明方法

  • public Method[] getDeclaredMethods()
    返回 Method 對象的一個數(shù)組,這些數(shù)組反映此 Class對象所表示的類或者接口聲明的的所有方法,包括公共、保護(hù)、默認(rèn)訪問和私有方法,但布包繼承的方法

三 Java反射機(jī)制應(yīng)用場景代碼演示

public class LLPerson implements Serializable {
    public String name;
    public int age;
    
    public LLPerson() {
    
    }
    public LLPerson(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat(String something) {
        Log.e("LLLLLLLL", "eat" + something);
    }
    //獲取類DemoTest的Class對象
            Class c = null;
            // 直接通過類名得到
            c = LLPerson.class;
            // 通過對象的 getClass() 方法獲取到
            Object object = new LLPerson();
            c = object.getClass();
            
            // 通過全類名獲取,用的比較多,
            c = Class.forName("com.example.liushaohua02.androidmolist.reflectActivity.LLPerson");
            //打印該Class對象表示的類的名稱
            Log.e(TAG, c.getName());
            
            //獲取該類的實(shí)例
            Log.e(TAG, "c:" +  c.newInstance());
            Log.e(TAG, "-------------------------------------------");
            
            //獲取該類實(shí)現(xiàn)的接口
            Class<?>[] interfaces = c.getInterfaces();
            System.out.println(interfaces[0].getName());
            Log.e(TAG, "-------------------------------------------");
            
            //獲取有參構(gòu)造函數(shù)
            Constructor<?> con = c.getConstructor(String.class, int.class);
            LLPerson dt = (LLPerson) con.newInstance("xiaoming", 12);
            Log.e(TAG, "age " + ((LLPerson) dt).getAge());
            Log.e(TAG, "-------------------------------------------");
                
            //獲取類的成員變量
            Field f2 = c.getField("age");
            Log.e(TAG, "Field" + f2);
            //獲取指定對象上該字段表示的值
            Log.e(TAG, "obj" + f2.get(dt));
            Log.e(TAG, "-------------------------------------------");
            //獲取指定的方法
            Method m = c.getMethod("eat", String.class);
            //反射調(diào)用方法,非常重要
            m.invoke(dt, "麥當(dāng)勞");        

四 Java 反射和 iOS 運(yùn)行時的對比

共同的優(yōu)點(diǎn):

  • 都可以實(shí)現(xiàn)的功能:獲取類信息,屬性設(shè)置獲取,類的動態(tài)加載,方法的動態(tài)調(diào)用
  • 提高程序的靈活性和擴(kuò)展性,能夠在運(yùn)行時動態(tài)的獲取類的實(shí)例
  • 和動態(tài)編譯相結(jié)合,可以提高更強(qiáng)大的功能
  • 提前無需硬編碼,便可以通過類名獲取對應(yīng)類的實(shí)例,進(jìn)而操作該實(shí)例。
    不同點(diǎn):
  • OC 能動態(tài)的給 class 添加類和方法,Java 不行:OC 運(yùn)行時對 類方法的調(diào)用是通過全局名稱查詢,而 Java VM 是通過類似 C++的虛表機(jī)制。
    此處想了解 OC的運(yùn)行時可看之前的一篇文章 《Runtime》
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容