java學習之反射機制

来源:https://www.cnblogs.com/0x3e-time/archive/2022/04/18/16155407.html
-Advertisement-
Play Games

反射機制雖然說增加了代碼的複雜程度但是提高代碼的靈活性,在以後的框架的學習中,配置文件的修改大部分都是利用的反射機制。和利用反射機制去做Runtime類這下麵方法exec,進行命令執行,後面去學習一下 ...


0x00前言和思維導圖

1.反射機制定義:java反射機制是指在java代碼執行過程中,對於任意一個類,可以獲取這個類的屬性與方法;對於任意一個對象,可以獲取、修改這個對象的屬性值,調用對象的方法。這種動態獲取信息和調用方法的技術就是java中的反射機制。
2.首先需要瞭解Class類(全限定名稱是java.lang.Class)和class對象。class對象就是由Class類創建的對象,只是這個創建過程不是由用戶主動創建的,而是由JVM自動實現的。JVM會為項目中每一個類(不論是JDK自帶的類、第三方jar包的類、還是自己編寫的類)創建一個class對象,用來保存與這個類相關的信息。class對象只與類有關,與對象無關。

0x01獲取位元組碼文件

方法一:Class.forName(" "),中間需要一個String類型的classname;
Class c3=Class.forName("java.util.Date");(它的執行胡導致類的載入會導致靜態模塊的代碼執行)
方法二:每個對象都有一個繼承與Object的方法叫做getClass;返回的是一個Class
public final native Class<?> getClass();
方法三:java每一種數據類型都用有一個屬性叫做class屬性
Class Z=String.class;

class My_Reflect_one{
    public static void main(String[] args) {
        Class c1=null;
        try {
            c1 = Class.forName("java.lang.String");
            Class c3=Class.forName("java.util.Date");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        String s="abc";
        Class X=s.getClass();
        System.out.println(c1==X);//返回值是True,位元組碼文件裝載到JVM的時候只會裝載一份
        Class Z=String.class;
        Class y=Integer.class;
    }
}}

0x02獲取Field(獲取屬性)

1.先定義一個類

class ReflectTest{
    public  int no=0;
    private String name;
    protected int age;
    boolean flag;
}

2.getFields()獲取所有是public修飾的屬性

public static void main(String[] args) throws  Exception{
        Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
        Field[] fields= Test_Class.getFields();}

3.getDeclaredFields()獲取所有屬性暴力破解,不管修飾符

public static void main(String[] args) throws  Exception{
   Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
   Field[] fs= Test_Class.getDeclaredFields();//暴力獲取所有屬性
          System.out.println(fs.length);//4個長度}

4.getTyp()獲取數據類型
(1)看下構造函數,返回值是一個Class

 public Class<?> getType() {
        return type;
    }

 public static void main(String[] args) throws  Exception{
        Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
        Field[] fs= Test_Class.getDeclaredFields();//暴力獲取所有屬性
                System.out.println(fs.length);//4個長度
                for (Field field :fs){
                    Class filedtype=field.getType();//接受返回的Class
                    String fName=filedtype.getName();//調用getname方法
                    System.out.println(fName);
                    System.out.println(field.getName());
                }}
        

5、getModifiers()和Modifier.toString()去找到屬性的修飾符
(1)構造函數 public int getModifiers()它的返回值是一個intpublic static String toString(int mod)它可以把對應的int輸出成對應的修飾符

public static void main(String[] args) throws  Exception{
       Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
       Field[] fs= Test_Class.getDeclaredFields();//暴力獲取所有屬性
               System.out.println(fs.length);//4個長度
               for (Field field:fs){
                   int  i=field.getModifiers();
                   String modifiter =Modifier.toString(i);
                   System.out.println(modifiter);    
                    }}

6.通過get和set方法訪問和修改屬性
(1)通過newInstance()方法構造出一個對象
(2)通過getDeclaredField(name)獲取一個屬性的值賦值給一個Field對象,可以同Filed對象.get/set
(3)get和set的構造方法
a.set():public void set(Object obj, Object value)
b.get(): public Object get(Object obj)

class Reflect_four{
    public static void main(String[] args) throws Exception {
        Class Test_class=Class.forName("zhonglin.www.ReflectTest");
        //操作對象屬性
        Object obj= Test_class.newInstance();
        Field nofiled=Test_class.getDeclaredField("no");
        nofiled.set(obj,2222);
        System.out.println(nofiled.get(obj));
        //訪問私有屬性
        Field namefield=Test_class.getDeclaredField("name");
        namefield.setAccessible(true);//打破封裝
        namefield.set(obj,"jsckson");
        System.out.println(namefield.get(obj));


    }
}

7.反編譯文件(拓展)
綜合使用學習到的方法

class Myreflect_Three{//構造好框架
    public static void main(String[] args) throws Exception {
        StringBuilder stringBuilder=new StringBuilder();
        Class Test_class=Class.forName("zhonglin.www.ReflectTest");
        stringBuilder.append(Modifier.toString(Test_class.getModifiers())+"class "+Test_class.getSimpleName()+"{");
        Field[] fields=Test_class.getDeclaredFields();
        stringBuilder.append("\n");
        for (Field field:fields)
        {
            stringBuilder.append("\t");
            stringBuilder.append(Modifier.toString(field.getModifiers()));//獲取屬性的修飾符
            stringBuilder.append(" ");
            stringBuilder.append(field.getType().getSimpleName());//獲取屬性類型
            stringBuilder.append(" ");
            stringBuilder.append(field.getName());//獲取屬性的名字
            stringBuilder.append(";\n");
        }
        stringBuilder.append("}");
        System.out.println(stringBuilder);
    }
}

0x02反射Method

1.基礎方法和反射屬性差不多。
2.方法的使用

***getDeclaredMethod("方法名",...args(參數))獲取方法
getReturnType()獲取返回值類型
Modifier.toString((method1.getModifiers())獲取修飾符
public Object invoke(Object obj, Object... args)調用方法***

3.看一下完整代碼

class Reflect_five{
    public static void main(String[] args) throws Exception {
        Class Test_class=Class.forName("zhonglin.www.ReflectTest2");
        Method[] method = Test_class.getDeclaredMethods();//獲取全部方法
        for (Method method1:method){
            System.out.println(method1.getName());
            //獲取返回值類型1
            System.out.println(method1.getReturnType());
            //獲取方法的修飾符
            System.out.println(Modifier.toString((method1.getModifiers())));
            //獲取參數列表
            Class[] classes=method1.getParameterTypes();
            for (Class parmeterType:classes){
                System.out.println(parmeterType.getSimpleName());
            }
        }
    }
}
class Reflect_six{
    public static void main(String[] args) throws  Exception{
        Class Test_class=Class.forName("zhonglin.www.ReflectTest2");
        Object obj=Test_class.newInstance();
        Method LONIN=Test_class.getDeclaredMethod("longin", String.class, String.class);
        Object result=LONIN.invoke(obj,"root","root");

    }

}

0x03反射Constructor

1.基礎方法一致:

getModifiers()隨後用toString輸出;//獲取修飾符
getSimpleName()//獲取構造方法名其實就是獲取類名
getParameterTypes()//獲取參數列表
public T newInstance();//創建一個對象,這個對象可以用一個Object去獲取,創建成功及調用了構造函數

點擊查看代碼
class Refldct_seven{
    public static void main(String[] args) throws Exception{
        StringBuilder stringBuilder=new StringBuilder();
        Class class_Test=Class.forName("zhonglin.www.ReflectTest3");
        stringBuilder.append(class_Test.getSimpleName());
        stringBuilder.append("{");
        stringBuilder.append("}");
        System.out.println(stringBuilder);
        Constructor[] constructors=class_Test.getDeclaredConstructors();
        for (Constructor constructor:constructors){
            System.out.println(constructor.getDeclaringClass().getSimpleName());
            constructor.getModifiers();
            constructor.getParameterTypes();
        }
        //創建對象
        Object obj= class_Test.newInstance();
        System.out.println(obj);
        //有參構造方法怎麼調用
        Constructor constructor2=class_Test.getDeclaredConstructor(int.class,String.class,String.class);
        Object obj2= constructor2.newInstance(2,"hellow","hellow");

    }
}
###0x4反射父介面和父類

1.學到這裡發現其實都是一些方法的使用
getSuperclass(): public native Class getSuperclass();//獲取父類 getInterfaces():public Class[] getInterfaces();//獲取全部介面返回值是一個路徑可用迴圈獲得

//看下實例;

class Refldct_eight{
    public static void main(String[] args) throws Exception{
        Class class_Test=Class.forName("zhonglin.www.ReflectTest4");
        class_Test.getSuperclass().getSimpleName();
        Class[] in= class_Test.getInterfaces();
        for (Class IN: in) {
            System.out.println(IN.getSimpleName());

        }

    }
}

0x05

反射機制雖然說增加了代碼的複雜程度但是提高代碼的靈活性,在以後的框架的學習中,配置文件的修改大部分都是利用的反射機制。和利用反射機制去做Runtime類這下麵方法exec,進行命令執行,後面去學習一下


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • RocketMQ消費端 今天要來跟大家學習怎樣使用RocketMQ來進行消息的消費 先簡單創建個Maven項目使用 添加依賴 <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-client</artifa ...
  • 函數是帶名字的代碼塊,要執行函數定義的特定任務,可調用該函數。 需要在程式中多次執行同一項任務時,你無需反覆編寫完成該任務的代碼,而只需調用執行該任務的函數,通過使用函數,程式的編寫、閱讀、測試和修複都將更容易。主程式文件的組織更為有序 一、如何定義一個函數 使用關鍵字 def 來定義一個函數。 d ...
  • #尾部加”/”匹配useTrailingSlashMatch ##參數初始化 參數初始化取決於requestMapping這個bean,這個bean在spring的IOC容器中初始化 我們重載一下requestMapping這個類即可 而在springboot中的初始化的bean名稱預設是reque ...
  • 對於一些帶著固定標簽的欄位來說,我們通常把它們配置到欄位中,而在資料庫中存它們的字典code,或者是字典主鍵,不是一個整型的數字,而在前端顯示時,有時需要將它們翻譯成名稱,這時後端可以幫他們進行翻譯,或者前端通過code自己使用字典翻譯;下麵說一下第一種,後端在View model中將integer ...
  • 定義 是指在讀取一行數據時,記下它的版本號、最近修改的時間戳或校驗和。然後,你可以在修改記錄之前檢查版本有沒有發生變化。 適用場景 適用於讀多寫少的場景,樂觀鎖相信事務之間的數據競爭概率較小,因此儘可能地直接做下去,直到提交的時候才去鎖定。 實現方式 取出記錄時,獲取當前 version 執行更新時 ...
  • 怎麼會有人不喜歡花呢?今天我們也來鑒定一下網路熱門植物!最近春天很多花都開了,我正好趁著清明假期到戶外踏青並拍攝 了不少花卉的照片。 由於對很多花不是特別熟悉,所以我們需要藉助軟體來識別究竟是什麼花的種類。市面上的識花軟體有很多,比如花伴侶、形 色、百度等等,我測試後發現百度的識別效果最為優秀。於是 ...
  • BlockingQueue阻塞隊列 BlockingQueue的四組API /**BlockQueue的四組API * 1.拋出異常 * 2.有返回值,不拋出異常 * 3.阻塞等待 * 4.超時等待 */public class BlockQueueTest { public static void ...
  • 前言 大家之前用python編寫過飛機大戰的部分代碼,只能夠展示英雄飛機,背景,敵機和發射子彈,今天把背景音樂,擊毀敵機,爆 炸特效,得分等等相關功能一併加入進來,代碼有點長,三百多行,你們要的代碼來了哦? 編程思路 主要使用pygame庫,類的創建,函數的調用等等來實現,話不多說,上程式。 編程實 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...