Java反射獲取類和對象信息全解析

2021-02-19 尚學堂

來源:segmentfault

反射可以解決在編譯時無法預知對象和類是屬於那個類的,要根據程序運行時的信息才能知道該對象和類的信息的問題。

在兩個人協作開發時,你只要知道對方的類名就可以進行初步的開發了。

獲取類對象

具體使用還是要根據實際來選擇,第一種方式是比較自由的,只要知道一個類名就可以了,其不會做該類是否存在的校驗,第二種、第三種則會做校驗


獲取類的信息
獲取類構造器


Connstructor<T> getConstructor(Class<?>...parameterTypes):返回此Class對象對應類的帶指定形參的public構造器

Constructor<?>[] getConstructors():返回此Class對象對應類的所有public構造器

Constructor<T>[] getDeclaredConstructor(Class<?>...parameterTypes):返回此class對象對應類的帶指定參數的構造器,與構造器的訪問權限無關

Constructor<?>[] getDeclaredConstructors():返回此class對象對應類的所有構造器,與構造器的訪問權限無關


獲取類成員方法

Method getMethod(String name,Class<?>...parameterTypes):返回此class對象對應類的帶指定形參的public方法

Method[] getMethods():返回此class對象所表示的類的所有public方法

Method getDeclaredMethod(string name,Class<?>...parameterTypes):返回此class對象對應類的帶指定形參的方法,與方法訪問權限無關

Method[] getDeclaredMethods():返回此class對象對應類的全部方法,與方法的訪問權限無關


獲取類成員變量


Field getField(String name):返回此class對象對應類的指定名稱的public成員變量

Field[] getFields():返回此class對象對應類的所有public成員變量

Field getDeclaredField(String name):返回此class對象對應類的指定名稱的成員變量,與成員變量訪問權限無關

Field[] getDeclaredFields():返回此class對象對應類的全部成員變量,與成員變量的訪問權限無關


獲取類註解

<A extends Annotation>A getAnnotation(Class<A>annotationClass):嘗試獲取該class對象對應類上村子的指定類型的Annotation,如果該類型註解不存在,則返回null

<A extends Annotation>A getDeclaredAnnotation(Class<A>annotationClass):這是Java 8中新增的,該方法獲取直接修飾該class對象對應類的指定類型的Annotation,如果不存在,則返回null

Annotation[] getAnnotations():返回修飾該class對象對應類上存在的所有Annotation

Annotation[] getDeclaredAnnotations():返回修飾該Class對象對應類上存在的所有Annotation

<A extends Annotation>A[] getAnnotationByType(Class<A>annotationClass):該方法的功能與前面介紹的getAnnotation()方法基本相似,但由於Java8增加了重複註解功能,因此需要使用該方法獲取修飾該類的指定類型的多個Annotation

<A extends Annotation>A[] getDeclaredAnnotationByType(Class<A>annotationClass):該方法發功能與前面介紹的getDeclaredAnnotations()方法相似,也是因為Java8的重複註解的功能,需要使用該方法獲取直接修飾該類的指定類型的多個Annotation


獲取該類內部類
獲取該類對象所在的外部類獲取該類對象對應類所實現的接口獲取該類對象對應類所繼承的父類
獲取該類對象對應類的修飾符、所在包、類名等基本信息

int getModifiers():返回此類或接口的所有修飾符,修飾符由public、protected、private、final、static、abstract等對應的常量組成,返回的整數應使用Modifier工具類的方法來解碼,才可以獲取真是的修飾符

Package getPackage():獲取該類的包

String getName():以字符串形式返回此CLass對象所表示的類的簡稱


判斷該類是否為接口、枚舉、註解類型

boolean isAnnotation():返回此class對象是否表示一個註解類型

boolean isAnnotationPresent(Class<? extends Annotation>annotationClass):判斷此Class對象是否使用類Annotation修飾

boolean isAnonymousClass():返回此class對象是否是一個匿名類

boolean isArray():返回此class對象是否表示一個數組類

boolean isEnum():返回此class對象是否表示一個枚舉

boolean isInterface():返回此class對象是否表示一個接口

boolean isInstance(Object obj):判斷obj是否是此class對象的實例,該方法可以完全代替instanceof操作符

public interface Colorable {     public void value();}

public class ClassInfo {    public static void main(String[] args) throws NoSuchMethodException, SecurityException {        Class<Colorable> cls=Colorable.class;        System.out.println(cls.getMethod("value"));        System.out.println(cls.isAnnotation());        System.out.println(cls.isInterface());    }}

結果

public abstract void com.em.Colorable.value()falsetrue


Java8中新增的方法參數反射

int getParameterCount():獲取該構造器或方法的形參個數

Parameter[] getParameters():獲取該構造器或方法的所有形參

getModifiers():獲取修飾該形參的修飾符

String getName():獲取形參名

Type getParameterizedType():獲取帶泛型的形參類型

Class<?>getType():獲取形參類型

boolean isNamePresent():該方法返回該類的class文件中是否包含了方法的形參名信息

boolean isVarArgs():該方法用於判斷該參數是否為個數可變的形參

public class Test {    public void getInfo(String str,List<String>list){        System.out.println("成功");    }}

public class ClassInfo {    public static void main(String[] args) throws NoSuchMethodException, SecurityException {        Class<Test> cls=Test.class;        Method med=cls.getMethod("getInfo", String.class,List.class);        System.out.println(med.getParameterCount());        Parameter[] params=med.getParameters();        System.out.println(params.length);        for(Parameter par:params){            System.out.println(par.getName());            System.out.println(par.getType());            System.out.println(par.getParameterizedType());        }    }}

結果

22arg0class java.lang.Stringclass java.lang.Stringarg1interface java.util.Listjava.util.List<java.lang.String>


反射生成對象
反射調用方法

public class Test {    public Test(String str) {        System.out.println(str);    }    public void getInfo(String str){        System.out.println(str);    }}

public class ClassInfo {    public static void main(String[] args) throws Exception {        Class<Test> cls=Test.class;        Constructor<Test>construct=cls.getConstructor(String.class);        Test test=construct.newInstance("初始化");        Method med=cls.getMethod("getInfo", String.class);        med.invoke(test, "調用方法成功");    }}

結果

初始化調用方法成功

接下來看官仔細看下面的慄子

public class Test {    public Test(String str) {        System.out.println(str);    }    //私有方法    private void getInfo(String str){        System.out.println(str);    }}

public class ClassInfo {    public static void main(String[] args) throws Exception {        Class<Test> cls=Test.class;        Constructor<Test>construct=cls.getConstructor(String.class);        Test test=construct.newInstance("初始化");      //為啥使用這個方法呢?        Method med=cls.getDeclaredMethod("getInfo", String.class);      //為啥使用這個方法呢?        med.setAccessible(true);        med.invoke(test, "調用方法成功");    }}

結果

初始化調用方法成功

setAccessible(boolean flag):將值設為true,指示該Method在使用是應該取消Java語言的訪問權限檢查


訪問成員變量值

getXxx(Object obj):獲取obj對象的該成員變量的值。此處的Xxx對應8種基本類型,如果該成員變量的類型是引用類型的,則去掉Xxx部分

setXxx(Object obj,Xxx val):將obj對象的該成員變量設置為val值。此處的Xxx對應8中基本類型,如果該成員變量的類型是引用類型,則取消set後面的Xxx

以上兩個方法可以方法所有的成員變量,包括private的私有成員變量

public class Test {    private int num;    public Test(String str) {        System.out.println(str);    }    private void getInfo(String str){        System.out.println(str);    }    public int getNum() {        return num;    }    public void setNum(int num) {        this.num = num;    }}

public class ClassInfo {    public static void main(String[] args) throws Exception {        Class<Test> cls=Test.class;        Constructor<Test>construct=cls.getConstructor(String.class);        Test test=construct.newInstance("初始化");        Method med=cls.getDeclaredMethod("getInfo", String.class);        med.setAccessible(true);        med.invoke(test, "調用方法成功");        Field fld=cls.getDeclaredField("num");        fld.setAccessible(true);        fld.setInt(test, 12);        System.out.println(fld.getInt(test));    }}

結果

初始化調用方法成功12


操作數組


java.lang.reflect包下有一個Array類,其可以動態創建數組

static Object newInstance(Class<?>componentType,int...length):創建一個具有指定的元素類型、指定維度的新數組

static xxx getXxx(Object array,int index):返回array數組中第index個元素。其中xxx是各種基本數據類型,如果數組元素是引用類型,則該方法變為get()

static void setXxx(Object array,int index,xxx val):將array數組中低index 個元素的值設為val,其中xxx是各種基本數據類型,如果數組元素是引用類型,則該方法變為set()

public class ArrayInfo {    public static void main(String[] args) {        Object arrays=Array.newInstance(String.class, 3);        Array.set(arrays, 0, "第一個");        Array.set(arrays, 1, "第二個");        Array.set(arrays, 2, "第三個");        System.out.println(Array.get(arrays, 2));    }}

尚學堂:每天推送IT新技術文章,跟著我們擴展技術視野吧

即刻起關注尚學堂,發送「要課程」,

IT課程免費送!

相關焦點

  • 「JAVA」萬字長篇詳述字節碼對象與反射機制完成動態編程
    在Java 中有兩種方式可以得到運行時信息:一是通過RTTI,即Run-Time Type Identification,這種方式假設我們在程序編寫時就已經知道了所有對象的類型,主要是通過字節碼對象Class來獲取;二是通過「反射」機制,反射提供一組api,通過調用api,便能獲取運行時的類信息;Java 中通過java.lang.reflect類庫來支持反射;
  • Java 類型信息詳解和反射機制
    從入門到精通實戰課程分享1、RTTIRTTI(RunTime Type Information)運行時類型信息,能夠在程序運行時發現和使用類型信息,把我們從只能在編譯期知曉類型信息並操作的局限中解脫出來傳統的多態機制正是 RTTI 的基本使用:假設有一個基類 Shape 和它的三個子類 Circle、Square、Triangle,現在要把
  • Java基礎教程:java反射機制教程
    Java反射說的是在運行狀態中,對於任何一個類,我們都能夠知道這個類有哪些方法和屬性。很多動力節點的學員在面試中都會被問到Java反射機制這個問題,為了幫助大家更好的掌握這個知識點,小編整理了一些資料分享給大家。
  • Java 反射,這篇寫的很透徹!
    而反射則相反,是根據Person對象,獲取到Class對象,然後可以獲取到Person類的相關信息,進行初始化或者調用等一系列操作。在運行狀態時,可以構造任何一個類的對象,獲取到任意一個對象所屬的類信息,以及這個類的成員變量或者方法,可以調用任意一個對象的屬性或者方法。可以理解為具備了動態加載對象以及對對象的基本信息進行剖析和使用的能力。
  • Java基礎之反射篇
    Java基礎之反射篇「Hello,大家好!我是老醜。今天給大家帶來的知識點是反射」1. 反射是什麼?反射(Reflection),它允許在運行中的Java程序獲取自身的信息,並且可以操作類或者對象的內部屬性。2. 反射可以做什麼?3.
  • 8千字java反射乾貨|java反射精講
    java反射機制精講目錄1. 反射機制的概念2. 反射的基礎Class類3. 反射的用法4.反射的應用示例反射機制的概念:在運行狀態中,對於任意一個類,都能夠獲取到這個類的所有屬性和方法,對於任意一個對象,都能夠調用它的任意一個方法和屬性(包括私有的方法和屬性),這種動態獲取的信息以及動態調用對象的方法的功能就稱為java語言的反射機制。反射被視為動態語言的關鍵。簡單來說反射就是java的各種成分映射成對應的java類。
  • 阿里P8教你Java註解與反射
    Java 語言中的類、方法、變量、參數和包等都可以被標註。和 Javadoc 不同,Java 標註可以通過反射獲取標註內容。在編譯器生成類文件時,標註可以被嵌入到字節碼中。Java 虛擬機可以保留標註內容,在運行時可以獲取到標註內容 。當然它也支持自定義 Java 標註。
  • Java 基礎與提高幹貨系列—Java 反射機制
    正文Java反射機制定義Java反射機制是指在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。用一句話總結就是反射可以實現在運行時可以知道任意一個類的屬性和方法。
  • 反射——Java高級開發必須懂得
    三、獲取方法信息知識點1:類裡面的標識符都有類類型。描述:創建一個工具類名稱為ClassUtil,並且有一個靜態方法,參數為Object類型參數,首先獲取該對象的類類型,這裡使用第二種獲取方式,傳遞的是哪個對象,Class對象就是該對象類類型(這個功能是由native聲明的一個方法實現的,java中jni就是做本地方法的,該方法是由java來聲明,用C語言來實現),萬事萬物皆對象,方法同樣是對象
  • Java反射機制深入詳解
    一.概念反射就是把Java的各種成分映射成相應的Java類。Class類的構造方法是private,由JVM創建。反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查並且對內部的成員進行操作。例如它允許一個java的類獲取他所有的成員變量和方法並且顯示出來。
  • Java面試高頻考點:反射機制使用大全
    作為一個Java開發工程師,在面試的過程中,反射機制也是經常會被問到的一個問題。例如Spring的IOC實現機制,其底層都是依賴於java的反射機制,因此,這是一個非常重要的知識點。對於初學java的同學來說,掌握其使用方法很有必要。
  • Java代碼審計基礎之反射
    先來一段反射的概念:在程序運行的時候動態裝載類,查看類的信息,生成對象,或操作生成對象。
  • Java語言的反射機制
    Java提供了一套機制來動態獲取類的信息以及動態調用對象的方法的功能,這套機制就叫——反射反射機制是如今很多流行框架的實現基礎,其中包括SSH(Struts、Spring、Hibernate)和SSM(SpringMVC、Spring、MyBatis)等。
  • Java反射,泛型在Json中的運用
    最近項目中遇到了Json數據自動獲取的功能,不然令人想起java的反射,已經很長時間沒複習java了正好一塊連java的這一塊內容一起過一遍。java中的反射無疑就相當於java開發者的春天,在眾多的框架中也能看到它的身影,可以在運行時檢查類,接口、變量和方法等信息,可以實例化調用方法以及設置變量值等。本文主要以代碼的形式直接將反射,泛型的運用展現出來。java中的反射首先新建一個基礎類Author。
  • 課程設計指導——如何應用Java反射技術靈活地創建程序類對象實例
    利用JDK系統庫中的java.util.Properties類中的load方法可以加載屬性文件和利用Properties類中的getProperty方法獲得屬性文件中的指定屬性項目。3、利用Java反射技術動態創建程序類的對象實例(1)Java反射(Reflection)機制主要提供的功能Java程式設計師充分地應用反射技術,能夠在程序代碼中實現在運行時判斷任意一個對象所屬的類類型、也能夠在運行時構造任意一個類的對象實例,當然還能夠在運行時判斷任意一個類所具有的成員變量和方法
  • Java 反射機制你還不會?那怎麼看 Spring 源碼?
    變為Person.class文件(字節碼文件),字節碼文件中,主要有類的屬性、構造函數、方法,當然還有類的其他信息,這個階段稱為源碼階段,通過類加載器進入內存,在內存中生成一個Class對象,這個階段為Class類對象階段,一個類的Class對象中存儲了類的全部信息,使用這個類對象的階段稱為Runtime運行時階段一種是傳統的RTTI(Run-Time Type Identification
  • java如何通過反射操作欄位
    我照樣要訪問》這三篇文章,描述了通過java反射創建對象以及調用方法,有興趣的朋友可以翻閱一下。今天我再來寫寫怎麼通過反射操作欄位吧。老規矩,先上我們要操作的類的代碼。這個demo類比較簡單,一個非靜態的欄位name,一個靜態的欄位staticName,都賦值了初始值。
  • 學Java反射,看這篇就夠了 | 原力計劃
    我們來一句話定義反射:反射就是把 Java 類中的各種成分映射成一個個的 Java 對象。不理解這句話什麼意思?沒關係,在我百度了幾分鐘後,找到三種解釋:解釋一:一個類有:成員變量、方法、構造方法、包等等信息,利用反射技術可以對一個類進行解剖,把各個組成部分映射成一個個對象。
  • 什麼是JAVA反射機制,詳細解讀JAVA面試的核心技術
    一、什麼叫Java反射機制?Java中的反射機制是指在運行狀態中,對於任意一個類,能夠動態獲取這個類中的屬性和方法;對於任意一個對象,都能夠任意調用它的屬性和方法。這種動態獲取類的信息以及動態調用對象方法的功能稱為Java的反射機制。
  • 理解Java反射的正確姿勢
    反射就是在運行狀態能夠動態的獲取該類的屬性和方法,並且能夠任意的使用該類的屬性和方法,這種動態獲取類信息以及動態的調用對象的方法的功能就是反射。在JVM中Class文件都與一個Class對象對應,在因為Class對象中包含著該類的類信息,只要獲取到Class對象便可以操作該類對象的屬性與方法。在這裡深入理解反射之前先來深入的理解Class對象,它包含了類的相關信息。