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
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...