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

什么是反射?
在java開(kāi)發(fā)中有一個(gè)非常重要的概念就是java反射機(jī)制,也是java的重要特征之一。反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪(fǎng)問(wèn)、檢測(cè)和修改它本身狀態(tài)或行為的一種能力,通過(guò)反射可以調(diào)用私有方法和私有屬性,大部分框架也都是運(yùn)用反射原理的。java通常是先有類(lèi)再有對(duì)象,有對(duì)象就可以調(diào)用方法或者屬性,java中的反射其實(shí)是通過(guò)Class對(duì)象來(lái)調(diào)用類(lèi)里面的方法。
反射的功能:
①在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類(lèi);
②在運(yùn)行時(shí)構(gòu)造任意一個(gè)類(lèi)的對(duì)象;
③在運(yùn)行時(shí)判斷任意一個(gè)類(lèi)所具有的成員變量和方法;
④在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法;
⑤生成動(dòng)態(tài)代理。
Java的反射機(jī)制它知道類(lèi)的基本結(jié)構(gòu),這種對(duì)Java類(lèi)結(jié)構(gòu)探知的能力,我們稱(chēng)為Java類(lèi)的“自審”。如eclipse中,一按點(diǎn),編譯工具就會(huì)自動(dòng)的把該對(duì)象能夠使用的所有的方法和屬性全部都列出來(lái),供用戶(hù)進(jìn)行選擇。這就是利用了Java反射的原理,是對(duì)我們創(chuàng)建對(duì)象的探知、自審。
反射常用類(lèi):
1.Class枚舉類(lèi)
Class 類(lèi)的實(shí)例表示正在運(yùn)行的 Java 應(yīng)用程序中的類(lèi)和接口。枚舉是一種類(lèi),注釋是一種接口。每個(gè)數(shù)組屬于被映射為 Class 對(duì)象的一個(gè)類(lèi),所有具有相同元素類(lèi)型和維數(shù)的數(shù)組都共享該 Class 對(duì)象?;镜?Java 類(lèi)型(boolean、byte、char、short、int、long、float 和 double)和關(guān)鍵字 void 也表示為 Class 對(duì)象。
Class 沒(méi)有公共構(gòu)造方法。Class 對(duì)象是在加載類(lèi)時(shí)由 Java 虛擬機(jī)以及通過(guò)調(diào)用類(lèi)加載器中的 defineClass 方法自動(dòng)構(gòu)造的。
Person p = new Person();
//獲取class對(duì)象的方式1
// 需要依賴(lài)
Class clazz = p.getClass();
// 方式2 在編譯之前就知道要操作的class的名稱(chēng)是什么
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)于類(lèi)的單個(gè)構(gòu)造方法的信息以及對(duì)它的訪(fǎng)問(wèn)權(quán)限。Constructor 允許在將實(shí)參與帶有基礎(chǔ)構(gòu)造方法的形參的 newInstance() 匹配時(shí)進(jìn)行擴(kuò)展轉(zhuǎn)換,但是如果發(fā)生收縮轉(zhuǎn)換,則拋出 IllegalArgumentException。

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


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


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

通常情況下我們只能在編寫(xiě)源代碼時(shí)能夠清楚的了解到對(duì)象的相關(guān)屬性和方法,常常這些方法是被固定的,程序進(jìn)入編譯之后變不能更改的,但是java加入了反射機(jī)制,便可以做到編譯之后還能對(duì)程序做出更改。
通過(guò)反射獲取對(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
// // 需要依賴(lài)
// Class clazz = p.getClass();
// // 方式2 在編譯之前就知道要操作的class的名稱(chēng)是什么
// 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();
}
}
那么為什么要使用這種方式來(lái)創(chuàng)建對(duì)象呢,原因很簡(jiǎn)單,使用反射來(lái)創(chuàng)建對(duì)象,最直接的原因就是因?yàn)?,在?xiě)底層代碼的時(shí)候,程序員對(duì)于要?jiǎng)?chuàng)建的對(duì)象有很多的不確定性,而正常的創(chuàng)建對(duì)象需要知道類(lèi)名,而很多使用在使用反射的創(chuàng)建對(duì)象時(shí),都是只給了個(gè)泛型,所以在不確定類(lèi)型的情況下創(chuàng)建對(duì)象是反射獨(dú)有的功能。
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java中數(shù)據(jù)轉(zhuǎn)換及字符串的“+”操作方法
本文主要介紹了Java中的數(shù)據(jù)類(lèi)型轉(zhuǎn)換,包括隱式轉(zhuǎn)換和強(qiáng)制轉(zhuǎn)換,隱式轉(zhuǎn)換通常用于將范圍較小的數(shù)據(jù)類(lèi)型轉(zhuǎn)換為范圍較大的數(shù)據(jù)類(lèi)型,而強(qiáng)制轉(zhuǎn)換則是將范圍較大的數(shù)據(jù)類(lèi)型轉(zhuǎn)換為范圍較小的數(shù)據(jù)類(lèi)型,本文介紹Java中數(shù)據(jù)轉(zhuǎn)換以及字符串的“+”操作,感興趣的朋友一起看看吧2024-10-10
Jmeter?BlazeMeter實(shí)現(xiàn)web錄制過(guò)程
BlazeMeter是一款與Apache JMeter兼容的chrome插件,采用BlazeMeter可以方便的進(jìn)行流量錄制和腳本生成,作為接口測(cè)試腳本編寫(xiě)的一個(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)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-11-11
Java實(shí)現(xiàn)對(duì)象復(fù)制的方法實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)對(duì)象復(fù)制的方法實(shí)例,深復(fù)制:復(fù)制出來(lái)的對(duì)象中的變量(包括基本類(lèi)型和字符串)和原來(lái)的對(duì)象的值都相同,引用對(duì)象也會(huì)指向復(fù)制出來(lái)的對(duì)象,需要的朋友可以參考下2023-08-08

