java反射機(jī)制最詳解
java反射機(jī)制

什么是反射?
在java開發(fā)中有一個(gè)非常重要的概念就是java反射機(jī)制,也是java的重要特征之一。反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測(cè)和修改它本身狀態(tài)或行為的一種能力,通過反射可以調(diào)用私有方法和私有屬性,大部分框架也都是運(yùn)用反射原理的。java通常是先有類再有對(duì)象,有對(duì)象就可以調(diào)用方法或者屬性,java中的反射其實(shí)是通過Class對(duì)象來調(diào)用類里面的方法。
反射的功能:
①在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類;
②在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象;
③在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法;
④在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法;
⑤生成動(dòng)態(tài)代理。
Java的反射機(jī)制它知道類的基本結(jié)構(gòu),這種對(duì)Java類結(jié)構(gòu)探知的能力,我們稱為Java類的“自審”。如eclipse中,一按點(diǎn),編譯工具就會(huì)自動(dòng)的把該對(duì)象能夠使用的所有的方法和屬性全部都列出來,供用戶進(jìn)行選擇。這就是利用了Java反射的原理,是對(duì)我們創(chuàng)建對(duì)象的探知、自審。
反射常用類:
1.Class枚舉類
Class 類的實(shí)例表示正在運(yùn)行的 Java 應(yīng)用程序中的類和接口。枚舉是一種類,注釋是一種接口。每個(gè)數(shù)組屬于被映射為 Class 對(duì)象的一個(gè)類,所有具有相同元素類型和維數(shù)的數(shù)組都共享該 Class 對(duì)象。基本的 Java 類型(boolean、byte、char、short、int、long、float 和 double)和關(guān)鍵字 void 也表示為 Class 對(duì)象。
Class 沒有公共構(gòu)造方法。Class 對(duì)象是在加載類時(shí)由 Java 虛擬機(jī)以及通過調(diào)用類加載器中的 defineClass 方法自動(dòng)構(gòu)造的。
Person p = new Person();
//獲取class對(duì)象的方式1
// 需要依賴
Class clazz = p.getClass();
// 方式2 在編譯之前就知道要操作的class的名稱是什么
Class clacc = Person.class;
Class clazz = Class.forName("com.openlab.test.Person");
Constructor[] con = clazz.getConstructors();
Method[] methods = clazz.getDeclaredMethods();
Field[] fields = clazz.getDeclaredFields();
System.out.println(con.length);
System.out.println(methods.length);
System.out.println(fields.length);



2.Constructor構(gòu)造器
Constructor 提供關(guān)于類的單個(gè)構(gòu)造方法的信息以及對(duì)它的訪問權(quán)限。Constructor 允許在將實(shí)參與帶有基礎(chǔ)構(gòu)造方法的形參的 newInstance() 匹配時(shí)進(jìn)行擴(kuò)展轉(zhuǎn)換,但是如果發(fā)生收縮轉(zhuǎn)換,則拋出 IllegalArgumentException。

3.Method方法類
Method 提供關(guān)于類或接口上單獨(dú)某個(gè)方法(以及如何訪問該方法)的信息。所反映的方法可能是類方法或?qū)嵗椒ǎòǔ橄蠓椒ǎ?br />
Method 允許在匹配要調(diào)用的實(shí)參與基礎(chǔ)方法的形參時(shí)進(jìn)行擴(kuò)展轉(zhuǎn)換;但如果要進(jìn)行收縮轉(zhuǎn)換,則會(huì)拋出 IllegalArgumentException。


4.Field變量類
Field 提供有關(guān)類或接口的單個(gè)字段的信息,以及對(duì)它的動(dòng)態(tài)訪問權(quán)限。反射的字段可能是一個(gè)類(靜態(tài))字段或?qū)嵗侄巍?br />
Array 允許在執(zhí)行 get 或 set 訪問操作期間進(jìn)行擴(kuò)展轉(zhuǎn)換,但如果將發(fā)生收縮轉(zhuǎn)換,則拋出一個(gè) IllegalArgumentException。


反射運(yùn)行指示圖

通常情況下我們只能在編寫源代碼時(shí)能夠清楚的了解到對(duì)象的相關(guān)屬性和方法,常常這些方法是被固定的,程序進(jìn)入編譯之后變不能更改的,但是java加入了反射機(jī)制,便可以做到編譯之后還能對(duì)程序做出更改。
通過反射獲取對(duì)象
package com.openlab.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
// Person p = new Person();
// //獲取class對(duì)象的方式1
// // 需要依賴
// Class clazz = p.getClass();
// // 方式2 在編譯之前就知道要操作的class的名稱是什么
// Class clacc = Person.class;
//
// Constructor[] con = clazz.getConstructors();
// Method[] methods = clazz.getDeclaredMethods();
// Field[] fields = clazz.getDeclaredFields();
//
// System.out.println(con.length);
// System.out.println(methods.length);
// System.out.println(fields.length);
// 方式3 常用
Class clazz;
try {
clazz = Class.forName("com.openlab.test.Person");
Constructor con = clazz.getDeclaredConstructor(new Class[]{String.class,int.class});
con.setAccessible(true);
Person p = (Person) con.newInstance(new Object[]{"張三瘋",99});
System.out.println(p);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Person p = (Person) clazz.newInstance();
}
}
那么為什么要使用這種方式來創(chuàng)建對(duì)象呢,原因很簡(jiǎn)單,使用反射來創(chuàng)建對(duì)象,最直接的原因就是因?yàn)?,在寫底層代碼的時(shí)候,程序員對(duì)于要?jiǎng)?chuàng)建的對(duì)象有很多的不確定性,而正常的創(chuàng)建對(duì)象需要知道類名,而很多使用在使用反射的創(chuàng)建對(duì)象時(shí),都是只給了個(gè)泛型,所以在不確定類型的情況下創(chuàng)建對(duì)象是反射獨(dú)有的功能。
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java中數(shù)據(jù)轉(zhuǎn)換及字符串的“+”操作方法
本文主要介紹了Java中的數(shù)據(jù)類型轉(zhuǎn)換,包括隱式轉(zhuǎn)換和強(qiáng)制轉(zhuǎn)換,隱式轉(zhuǎn)換通常用于將范圍較小的數(shù)據(jù)類型轉(zhuǎn)換為范圍較大的數(shù)據(jù)類型,而強(qiáng)制轉(zhuǎn)換則是將范圍較大的數(shù)據(jù)類型轉(zhuǎn)換為范圍較小的數(shù)據(jù)類型,本文介紹Java中數(shù)據(jù)轉(zhuǎn)換以及字符串的“+”操作,感興趣的朋友一起看看吧2024-10-10
Jmeter?BlazeMeter實(shí)現(xiàn)web錄制過程
BlazeMeter是一款與Apache JMeter兼容的chrome插件,采用BlazeMeter可以方便的進(jìn)行流量錄制和腳本生成,作為接口測(cè)試腳本編寫的一個(gè)基礎(chǔ),這篇文章主要介紹了Jmeter?BlazeMeter實(shí)現(xiàn)web錄制,需要的朋友可以參考下2021-12-12
SpringBoot屬性綁定與bean屬性校驗(yàn)實(shí)現(xiàn)方法詳解
這篇文章主要介紹了SpringBoot屬性綁定與bean屬性校驗(yàn)實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11
Java實(shí)現(xiàn)對(duì)象復(fù)制的方法實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)對(duì)象復(fù)制的方法實(shí)例,深復(fù)制:復(fù)制出來的對(duì)象中的變量(包括基本類型和字符串)和原來的對(duì)象的值都相同,引用對(duì)象也會(huì)指向復(fù)制出來的對(duì)象,需要的朋友可以參考下2023-08-08

