day44-反射03

来源:https://www.cnblogs.com/liyuelian/archive/2022/09/29/16743198.html
-Advertisement-
Play Games

Java反射03 3.通過反射獲取類的結構信息 3.1java.lang.Class類 getName:獲取全類名 getSimpleName:獲取簡單類名 getFields:獲取所有public修飾的屬性,包含本類以及父類的 getDeclaredFields:獲取本類中所有屬性 getMeth ...


Java反射03

3.通過反射獲取類的結構信息

3.1java.lang.Class類

  1. getName:獲取全類名
  2. getSimpleName:獲取簡單類名
  3. getFields:獲取所有public修飾的屬性,包含本類以及父類的
  4. getDeclaredFields:獲取本類中所有屬性
  5. getMethods:獲取所有public修飾的方法,包含本類以及父類的
  6. getDeclaredMethods:獲取本類中所有方法
  7. getConstructors:獲取本類中所有public修飾的構造器
  8. getDeclaredConstructors:獲取本類中所有構造器
  9. getPackage:以Package形式返回包信息
  10. getSuperClass:以Class形式返回父類信息
  11. getInterfaces:以Class形式返回介面信息
  12. getAnnotations:以Annotation形式返回註解信息

例子1:

package li.reflection;

import org.junit.jupiter.api.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//演示如何通過反射獲取類的結構信息
public class ReflectionUtils {
    public static void main(String[] args) {
    }

    //第一組方法 API
    @Test
    public void api_01() throws ClassNotFoundException {
        //得到Class對象
        Class<?> personCls = Class.forName("li.reflection.Person");

        //1. getName:獲取全類名
        System.out.println(personCls.getName());//li.reflection.Person

        //2. getSimpleName:獲取簡單類名
        System.out.println(personCls.getSimpleName());//Person

        //3. getFields:獲取所有public修飾的屬性,包含本類以及父類的
        Field[] fields = personCls.getFields();
        for (Field field : fields) {//增強for
            System.out.println("本類以及父類的屬性=" + field.getName());
            //本類以及父類的屬性=name
            //本類以及父類的屬性=hobby

        }

        //4. getDeclaredFields:獲取本類中所有屬性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本類中所有屬性=" + declaredField.getName());
        }

        //5. getMethods:獲取所有public修飾的方法,包含本類以及父類的
        //這裡的父類包括的不只是直接父類,包括object的共有方法也會獲取
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("獲取包含本類以及父類的所有public修飾的方法=" + method.getName());
        }

        //6. getDeclaredMethods:獲取本類中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("獲取本類中所有方法" + declaredMethod.getName());
        }

        //7. getConstructors:獲取本類中所有public修飾的構造器
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("本類的public構造器=" + constructor.getName());

        }

        //8. getDeclaredConstructors:獲取本類中所有構造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("獲取本類中所有構造器=" + declaredConstructor.getName());//這裡只是輸出名字
        }

        //9. getPackage:以Package形式返回包信息
        System.out.println(personCls.getPackage());//package li.reflection

        //10. getSuperClass:以Class形式返回父類信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println("父類的Class對象=" + superclass);//class li.reflection.A

        //11. getInterfaces:以Class形式返回介面信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("介面信息" + anInterface);
            //介面信息interface li.reflection.IA
            //介面信息interface li.reflection.IB
        }

        //12. getAnnotations:以Annotation形式返回註解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("註解信息" +annotation);//註解信息@java.lang.Deprecated()
        }
    }
}

class A {
    public String hobby;

    public void hi() {
    }

    public A() {
    }

}

interface IA {
}

interface IB {
}

@Deprecated
class Person extends A implements IA, IB {
    //屬性
    public String name;
    protected int age;
    String job;
    private double sal;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    //私有
    private Person(String name, int age) {
    }

    //方法
    public void m1() {
    }

    protected void m2() {
    }

    void m3() {
    }

    private void m4() {
    }

}

image-20220929180038787 image-20220929180103387

3.2java.lang.reflect.Field類

  1. getModifiers:以int形式返回修飾符

    [說明:預設修飾符default是0,public 是1 ,private是2,protected是4,static是8,final是16]

    如果有疊加的修飾符,如 public static ...,那麼返回的int值就是相加的結果,public(1)+static(8)=9

  2. getType:以Class形式返回類型,即返回該屬性對應的類的Class對象

  3. getName:返回屬性名

3.3java.lang.reflect.Method類

  1. getModifiers:以int形式返回修飾符

    [說明:預設修飾符default是0,public 是1 ,private是2,protected是4,static是8,final是16]

    如果有疊加的修飾符,如 public static ...,那麼返回的int值就是相加的結果,public(1)+static(8)=9

  2. getReturnType:以Class形式獲取返回值的類型的Class對象

  3. getName:返回方法名

  4. getParameteTypes:以Class[]返回參數類型數組

3.4java.lang.reflect.Constructor類

  1. getModifiers:以int形式返回修飾符
  2. getName:返回構造器名(全類名)
  3. getParameteTypes:以Class[]返回參數類型數組

例子2:使用Field類、Method類、Constructor類

package li.reflection;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//演示如何通過反射獲取類的結構信息
public class ReflectionUtils {
    public static void main(String[] args) {
    }

    //第二組方法 API
    @Test
    public void api_02() throws ClassNotFoundException {
        //得到Class對象
        Class<?> personCls = Class.forName("li.reflection.Person");

        //getDeclaredFields:獲取本類中所有屬性
        //[說明:預設修飾符default是0,public 是1 ,private是2,protected是4,static是8,final是16]
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本類中所有屬性=" + declaredField.getName()
                    + " 該屬性的修飾符值=" + declaredField.getModifiers()
                    + " 該屬性的類型=" + declaredField.getType());
        }

        //getDeclaredMethods:獲取本類中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本類中的所有方法=" + declaredMethod.getName()
                    + " 該方法的訪問修飾符=" + declaredMethod.getModifiers()
                    + " 該方法返回類型=" + declaredMethod.getReturnType());

            //輸出當前這個方法的形參數組情況
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("該方法的形參類型=" + parameterType);
            }
        }

        //getDeclaredConstructors:獲取本類中所有構造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("=================");
            System.out.println("本類中所有構造器=" + declaredConstructor);
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("該構造器的形參類型=" + parameterType);
            }
        }
    }
}

class A {
    public String hobby;

    public void hi() {
    }

    public A() {
    }

}

interface IA {
}

interface IB {
}

@Deprecated
class Person extends A implements IA, IB {
    //屬性
    public String name;
    protected static int age;
    String job;
    private double sal;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    //私有
    private Person(String name, int age) {
    }

    //方法
    public void m1(String name, int age, double sal) {
    }

    protected String m2() {
        return null;
    }

    void m3() {
    }

    private void m4() {
    }
}
image-20220929185203838 image-20220929185234966

4.通過反射創建對象

  1. 方式一:調用類中的public修飾的無參構造器
  2. 方式二:調用類中的指定構造器
  3. Class類的相關方法
    • newInstance:調用類中的無參構造器,獲取對應類的對象
    • getConstructor(Class...clazz):根據參數列表,獲取對應的public構造器對象
    • getDecalaredConstructor(Class...clazz):根據參數列表,獲取對應的所有構造器對象
  4. Constructor類相關方法
    • setAccessible:暴破
    • newInstance(Object...obj):調用構造器

例子:

package li.reflection;

import java.lang.reflect.Constructor;

//演示通過反射機制創建實例
public class ReflectCreatInstance {
    public static void main(String[] args) throws Exception {
        //1.先獲取到User類的Class對象
        Class<?> userClass = Class.forName("li.reflection.User");

        //2.通過public的無參構造器創建實例
        Object o = userClass.newInstance();
        System.out.println(o);

        //3.通過public的有參構造器創建實例
        /**
         *  此時的 constructor 對象 就是
         *   public User(String name) {//public有參構造器
         *      this.name = name;
         *     }
         */
        //3.1先得到對應的構造器
        Constructor<?> constructor = userClass.getConstructor(String.class);
        //3.2再去創建實例,並傳入實參
        Object bob = constructor.newInstance("bob");
        System.out.println(bob);

        //4.通過非public的有參構造器創建實例

        //4.1得到private的構造器對象
        Constructor<?> declaredConstructor =
                userClass.getDeclaredConstructor(int.class, String.class);
        //4.2創建實例
        //暴破(暴力破解),使用反射可以訪問 私有的構造器/私有的屬性/私有的方法
        declaredConstructor.setAccessible(true);
        Object user2 = declaredConstructor.newInstance(99, "張三豐");
        System.out.println(user2);
    }
}

class User {//User類
    private int age = 10;
    private String name = "jack";

    public User() {//public無參構造器
    }

    public User(String name) {//public有參構造器
        this.name = name;
    }

    private User(int age, String name) {//private有參構造器
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}
image-20220929194206872

5.通過反射訪問類中的成員

  • 訪問屬性

    1. 根據屬性名獲取Field對象

      Field f = class對象.getDeclaredField(屬性名);

    2. 爆破:f.setAccessible(true);//f是Field

    3. 訪問

      f.set(o,值);//o表示對象

      syso(f.get(o)); //o表示對象

    4. 註意:如果是靜態屬性,則set和get中的參數o,可以寫為null

例子:

package li.reflection;

import java.lang.reflect.Field;

//演示反射操作屬性Field
public class ReflectAccessProperty {
    public static void main(String[] args) throws Exception {
        //1.得到Student類對應的Class對象
        Class<?> stuClass = Class.forName("li.reflection.Student");
        
        //2.創建對象
        Object o = stuClass.newInstance();//o的運行類型就是Student
        System.out.println(o.getClass());//Student

        //3.使用反射得到age屬性對象(公有)
        Field age = stuClass.getField("age");
        age.set(o,88);//通過反射來操作屬性
        System.out.println(o);//Student [age=88, name = null]
        //或者
        System.out.println(age.get(o));//返回age屬性的值 88

        //4.使用反射操作name屬性(私有靜態的屬性)
        Field name = stuClass.getDeclaredField("name");
        //因為name是私有的屬性,需要對 name進行爆破
        name.setAccessible(true);
        name.set(o,"jack");//也可以寫name.set(null,"jack");因為name是靜態屬性,與類有關,與對象無關
        System.out.println(o);
        System.out.println(name.get(o));//jack
    }
}

class Student {
    public int age;
    private static String name;

    public Student() {
    }

    @Override
    public String toString() {
        return "Student [age=" + age + ", name = " + name + "]";
    }
}
image-20220929201419942
  • 訪問方法

    1. 根據方法名和參數列表獲取Method方法對象:

      Method m = 類的Class對象.getDeclaredMethod(方法名,XX.class);//得到本類的所有方法

      XX.class指方法的參數對應的class

    2. 獲取對象:Object o = 類的Class對象.newInstance();

    3. 爆破:m.setAccessible(true);

    4. 訪問:Object returnValue = m.invoke(o,實參列表);

    5. 註意:如果過是靜態方法,則invoke的參數o可以寫為null

例子:

package li.reflection;

import java.lang.reflect.Method;

//演示通過反射操作方法
public class ReflectAccessMethod {
    public static void main(String[] args) throws Exception {
        //1.得到Boss類對應的Class對象
        Class<?> bossCls = Class.forName("li.reflection.Boss");

        //2.創建對象
        Object o = bossCls.newInstance();

        //3.調用普通的public的hi方法
        //3.1得到hi方法對應的方法對象
        Method hi = bossCls.getMethod("hi", String.class);
        //3.2調用
        hi.invoke(o, "孫悟空");

        //4.調用private static 方法
        //註意點:1.private:要使用爆破;2.static:在invoke時的參數可以寫null
        //4.1得到 say 方法對象
        Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        //4.2爆破
        say.setAccessible(true);
        //4.3invoke的null
        System.out.println(say.invoke(o, 100, "張三", '男'));
        System.out.println(say.invoke(null, 999, "李四", '女'));//因為是靜態的方法,所以o可以寫為null

        //5.在反射中,如果方法有返回值,統一返回Object,但其運行類型和方法定義的返回類型一致
        Object reVal = say.invoke(null, 300, "jack", '男');
        System.out.println("reVal的運行類型=" + reVal.getClass());//String

    }
}

class Boss {
    public int age;
    private static String name;

    public Boss() {
    }

    private static String say(int n, String s, char c) {//靜態方法
        return n + " " + s + " " + c;
    }

    public void hi(String s) {//普通的public方法
        System.out.println("hi " + s);
    }
}
image-20220929205451785

6.本章作業

6.1練習1:通過反射修改私有成員變數

  1. 定義privateTest類,有私有屬性name,並且屬性值為"hellokitty"
  2. 提供getName的公有方法
  3. 創建PrivateTest的類,利用Class類的到私有屬性name,修改其屬性值,並調用getName()的方法列印name屬性值
package li.reflection.homework;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class homework01 {
    public static void main(String[] args) throws Exception {
        //1.得到PrivateTest對應的Class對象
        Class<?> privateTestCls = Class.forName("li.reflection.homework.PrivateTest");
        //2.創建對象
        Object o = privateTestCls.newInstance();
        //3.得到name屬性對象
        Field name = privateTestCls.getDeclaredField("name");
        //4.爆破
        name.setAccessible(true);
        name.set(o,"天龍八部");
        //5.得到getName方法的對象
        Method method = privateTestCls.getMethod("getName");
        //6.因為getName是public方法,直接調用即可
        Object invoke = method.invoke(o);
        System.out.println("name屬性的值="+invoke);
    }
}
class PrivateTest{
    private String name = "HelloKitty";
    public String getName(){
        return name;
    }
}
image-20220929211441091

6.2練習:利用反射和File完成以下功能

  1. 利用Class類的forName方法得到File類的class對象
  2. 在控制台列印File類的所有構造器
  3. 通過newInstance方法創建File對象,並創建d:\mynew.txt文件

提示:創建文件的正確寫法如下:

File file = new File("d:\mynew.txt");

file.creatNewFile();

package li.reflection.homework;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class homework02 {
    public static void main(String[] args) throws Exception {
        //得到File類對應的class類對象
        Class<?> fileCls = Class.forName("java.io.File");
        //得到所有的構造器
        Constructor<?>[] declaredConstructors = fileCls.getDeclaredConstructors();
        System.out.println("=====File的所有構造器=====");
        //遍歷輸出構造器
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        //指定得到 public java.io.File(java.lang.String)
        Constructor<?> constructor = fileCls.getConstructor(String.class);
        //創建File類對象
        Object file = constructor.newInstance("d:\\mynew.txt");
        //獲取createNewFile方法的對象
        Method createNewFile = fileCls.getDeclaredMethod("createNewFile");
        //調用
        createNewFile.invoke(file);
    }
}
image-20220929213900651 image-20220929213828260
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 語法&關鍵字與保留字 本章篇幅較長故分成幾個小節來講 語法 區分大小寫 這個沒啥好講的,a和A是兩個變數。 標識符 標識符,就是變數、函數、屬性或函數參數的名稱。 標識符的組成規範,如下: 第一個字元必須是一個字母、下劃線( _ )或者美元符號( $ ); 剩下的其他字元可以使字母、下劃線、美元符號 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 第一問:安全類型檢測——typeof和instanceof 區別以及缺陷,以及解決方案 這兩個方法都可以用來判斷變數類型 區別:前者是判斷這個變數是什麼類型,後者是判斷這個變數是不是某種類型,返回的是布爾值 (1)typeof 缺陷: 1 ...
  • 隨著NFC讀寫器在BS架構下的需求越來越多,使用JS語言在web瀏覽器下操作NFC讀寫器就變得尤其重要.但是web瀏覽器不允許其顯示內容直接操作硬體,所以我們必須使用IC卡讀卡器web插件來實現這個功能.作為web前端工程師,我們首先要瞭解在web中實現操作NFC讀寫器的步驟:1、下載友我科技IC卡 ...
  • NullPointerException在開發過程中經常遇到,稍有不慎小BUG就出現了,如果避免這個問題呢,Optional就是專門解決這個問題的類,那麼Optional如何使用呢?讓我們一起探索一下吧! ...
  • 一、項目優化 1.去掉列印console 需求:在開發環境中,保留列印console;在生產上線環境,自動去掉列印console 使用步驟: 第一步:在項目根目錄下,創建如下圖兩個配置文件 在.env.development中(開發環境變數) NODE_ENV=development 在.env.p ...
  • 裝飾器模式(Decorator Design Pattern)是一種結構型設計模式,通過將對象放入包含行為的特殊封裝對象中來為原對象綁定新的行為。簡單地說,就是允許向一個現有的功能添加新的功能,同時又不改變其結構。 ...
  • 介面 interface 介面就是一組規範(就像我們法律一樣),所有實現類都要遵守。 面向對象的精髓,最能體現這一點的就是介面。為什麼我們討論設計模式都只針對具備了抽象能力的語言(比如 C++、Java、C#等),就是因為設計模式所研究的,實際上就是如何合理的去抽象。 介面的作用 為什麼需要介面?接 ...
  • ##示例代碼 public class ArrayListSource { public static void main(String[] args) { ArrayList arrayList = new ArrayList(); //跳轉至第一步 for (int i = 0; i < 10; ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...