摘要:反射機制前言更多文章請一步本人博客網(wǎng)頁版的的離線版什么是反射機制反射是語言的一個特性,它允程序在運行時注意不是編譯的時候來進行自我檢查并且對內(nèi)部的成員進行操作。這個構(gòu)造器就是用的反射在動態(tài)加載的時候來獲取的中類的屬性的。
Java反射機制 前言
什么是反射機制更多文章請一步本人博客https://chenjiabing666.github.io/
網(wǎng)頁版的jdk的API
離線版API
主要的類反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查并且對內(nèi)部的成員進行操作。例如它允許一個java的類獲取他所有的成員變量和方法并且顯示出來。這個能特定我們不??吹剑窃谄渌谋热鏑或者C++語言中很不就存在這個特性。一個常見的例子是在JavaBean中,一些組件可以通過一個構(gòu)造器來操作。這個構(gòu)造器就是用的反射在動態(tài)加載的時候來獲取的java中類的屬性的。
ClassClass 類的實例表示正在運行的 Java 應用程序中的類和接口。Class沒有公共的構(gòu)造方法,Class 對象是在加載類時由 Java 虛擬機以及通過調(diào)用類加載器中的 defineClass 方法自動構(gòu)造的
Constructor 提供關于類的單個構(gòu)造方法的信息以及對它的訪問權(quán)限(主要提供的是對構(gòu)造方法使用)
Method 提供關于類或接口上多帶帶某個方法(以及如何訪問該方法)的信息。所反映的方法可能是類方法或?qū)嵗椒ǎòǔ橄蠓椒?
Field 主要提供對類中的成員變量的訪問和使用
常用的方法Class類也使用了泛型,即是Class
這種形式的,可以直接使用一個具體的類傳入,這樣的話就不需要強制轉(zhuǎn)換了,比如Class.newInstance()這樣使用默認的構(gòu)造方法構(gòu)造一個對象就需要不再需要強制轉(zhuǎn)換了即使用(ClassName)Class.newInstance()
獲取Class的對象并且實例化getConstructor(Class[] params) 獲取公共的(public)的構(gòu)造方法,并且限定其中的參數(shù)個數(shù)和類型可以獲得不同的公共構(gòu)造方法
Constructor[] getConstructors() 返回所有的公共(public)的構(gòu)造方法
getDeclaredConstructor(Class[] params) 獲取所有指定的構(gòu)造方法,但是需要注意的是當獲取私有的構(gòu)造方法的時候需要使用setAccessible設置訪問權(quán)限為true才能進行構(gòu)造,否則出現(xiàn)異常
Constructor[] getDeclaredConstructors() 返所有的構(gòu)造方法包括public和private,protected修飾的
T newInstance() 返回的是一個調(diào)用默認的構(gòu)造方法(public class_name())實例化的一個Object對象,如果使用泛型那么就返回T類型的,反之返回的是Object需要強制轉(zhuǎn)換才能使用這個對象調(diào)用成員函數(shù)和成員變量
Class forName(String class_name) 返回class對象,每一個對都有一個方象法返回Class對象(test.class)
Package getPackage() 返回此類所在的包名(package demo) 當然也可以使用Package.getName()獲得包的名字(demo)比如constructor.getPackage().getName()
int getModifiers() 返回的是類的修飾符的整數(shù) 類型(修飾符的類型有public private protected)其中得到整數(shù)可以使用Modifier中toString(int num)得到public,private,protected的類型,比如Modifier.toString(class1.getModifiers())
* Method getMethod(String name, Class>... parameterTypes) 返回指定參數(shù)的方法Method對象,注意這里僅僅是返回的時公共的方法(public) 比如:Method method=class1.getMethod("display",new Class[]{int.class})這里的display是方法的名字,有一個參數(shù),類型為intMethod[] getMethods() 獲取所有的公共的方法(public)返回的是一個數(shù)組(Method)
Method getDeclaredMethod(String name,Class>... parameterTypes)返回所有的指定的參數(shù)的方法(public,private,protected,但是不包括繼承的),其中參數(shù)可以為null(無參數(shù))
Method[] getDeclaredMethods() 獲取所有的方法
Field getField(String name) 指定名字的公共成員變量(public)
Field[] getFields() 獲取所有的公共的成員變量
Field getDeclaredField(String name) 獲取所有的指定名稱的成員變量(public,protected,private),同樣在調(diào)用私有成員變量的時候需要先設置訪問的權(quán)限,field.setAccessible(true)
Field[] getDeclaredFields() 獲取所有的成員變量(public,protected,private)
getSuperclass() 返回表示此 Class 所表示的實體(類、接口、基本類型或 void)的超類的 Class。
URL getResource(String name) 查找指定名稱的資源(圖片,文件...)注意這個資源一定要和指定類在一個包中,否則返回null,比如查找Test類下的airplane.png圖片:Test.class.getResource("airplane.png")這里返回的將是絕對路徑
使用Class.forName(String className) 其中className一定是包含包的名字,下面的demo就是包的名字,Test是類的名字。這是最常用的方法,學過JDBC的都知道加載驅(qū)動的時候就是使用的Class.forName()
/* * 第一種使用forName(String className),其中className一定是包含包的名字,下面的demo就是包的名字,Test是類的名字 */ Class cls=Class.forName("demo.Test"); Test test=(Test)cls.newInstance(); //這里只是使用了默認的構(gòu)造方法實例化對象
使用類名.class
Class cls=Test.class;
使用對象.getClass()
Test test=new Test(); Class cls=test.getClass();Constructor
常用的方法主要是用來對類的構(gòu)造方法進行操作的,可以看出這個也使用了泛型,和上面的Class是一樣的,注意這里如果沒有使用泛型,那么原本放回T類型的現(xiàn)在都是返回Object
MethodT newInstance(Object parms) 使用帶有參數(shù)的構(gòu)造方法實例化對象,如果使用了泛型,那么返回的就是T類型的,反之返回的是Object類型的,需要強制轉(zhuǎn)換
getName() 以字符串的形式返回構(gòu)造方法的名稱,具體的路徑包含包名(demo.Test)
int getModifiers() 和Class類中的方法一樣
常用的方法主要提供的是對類中的方法的操作
FieldObject invoke(Object obj,object args) 使用得到的Method對象調(diào)用方法,obj是類的已經(jīng)構(gòu)造好的對象,如果是靜態(tài)方法直接寫null,因為靜態(tài)方法的調(diào)用不需要對象,返回值是Object類型的,如果接受返回值,需要使用強制轉(zhuǎn)換成相應的類型,args是傳入的參數(shù),如果有多個參數(shù),那么可以直接在后面用逗號添加或者直接創(chuàng)建數(shù)組new Object[]{22,"chenjiabing"}比如:method.invoke(test,22,"chenjiabing") method.invoke(test,new Object[]{22,"chenjiabing"})注意:如果調(diào)用的private類型的方法,那么需要在前面設置訪問的權(quán)限,method.setAccessible(true)
String getName() 返回此方法的名字(display)
Modifier getModifiers() 返回此方法的修飾符的類型表示的整數(shù)(public,private...),可以使用Modifier.toString()轉(zhuǎn)換成字符串形式
Class getReturnType() 返回這個方法的返回類型
String toString() 返回這個方法表示的字符串的形式
常用方法主要提供對類的成員變量的操作
ModifierString getName() 返回變量名字
Object get(Object obj) 返回此變量在指定對象中的值,因為在構(gòu)造對象的時候每一個傳入的變量的值都不一樣,因此需要使用對象obj。obj表示傳入的對象,返回的Object類型,因此需要強制轉(zhuǎn)換
void set(Object obj,Object value) 改變obj對象上的變量的值為value
Modifier getModifiers() 返回整數(shù)表示修飾的類型
String getType() 獲取變量的類型(int,String,double float.....)
常用的方法Modifier 類提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。修飾符集被表示為整數(shù),用不同的位位置 (bit position) 表示不同的修飾符。
實例static String toString(int mode) 將代表修飾符的整數(shù)形式轉(zhuǎn)換為字符串形式的修飾符,比如將1轉(zhuǎn)換成public
static isInterface(int mode) 如果整數(shù)參數(shù)包括 interface 修飾符,則返回 true,否則返回 false
static isStatic(int mode)
static isPrivate(int mode)
static isPublic(int mode)
static isAbstract(int mode)
Modifier.toString(Test.class.getModifiers()) //得到Test類的修飾符使用
有了上面的鋪墊,我們就可以使用上面的這些類進行操作了,在進行操作之前,我們需要先定義一個類Test,放在demo包下,內(nèi)容如下
package demo; import java.util.jar.Attributes.Name; import javax.print.attribute.standard.MediaSize.NA; public class Test { public String name; private int age; public Test() { this.name = "陳加兵"; this.age = 23; } public Test(String name, int age) { this.name = name; this.age = age; } public void display() { System.out.println("name=" + this.name + "----age=" + this.age); } public void set(String name, int age) { this.name = name; this.age = age; } private int getAge() { return this.age; } }實例化對象
使用Class默認的構(gòu)造newInstance()
Class class1=Class.forName("demo.Test"); //靜態(tài)加載Class Test test=(Test)class1.newInstance(); //調(diào)用默認的構(gòu)造方法(public Test())實例化對象,由于沒有使用泛型,因此需要強轉(zhuǎn) test.display(); //調(diào)用display方法
使用Class中的getConstructor()方法構(gòu)造對象,需要注意的使用private類型構(gòu)造方法時一定要先設置訪問權(quán)限為true-constructor.setAccessible(true);
/* *調(diào)用public Test(String name,int age)得到Constructor的兩種形式 * 1.Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class}); * 2.Constructor constructor=class1.getConstructor(String.class,int.class);這個和上面的是一樣的,就是使用的參數(shù)形式不一樣 * * * * *使用newInstance()構(gòu)造對象的兩種方式 * 1.Test test=(Test)constructor.newInstance(new Object[]{"chenjiabing",22}); * 2.Test test=(Test)constructor.newInstance("chenjiabing",22); 只是形式不同而已,不過我還是喜歡上面的形式 * */ /* * 調(diào)用public Test(String name,int age) * Class.getConstructor()得到的是公共的構(gòu)造方法,如果有私有的構(gòu)造方法,那么就會報錯,這時就要使用getDeclaredConstructor(Class>... parameterTypes) * Test test=(Test)constructor.newInstance("陳加兵",22); * * * 調(diào)用public Test() * Constructor constructor=class1.getConstructor(null); * Test test=(Test)constructor.newInstance(null); * * * 調(diào)用private Test(int age) * Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class}); constructor.setAccessible(true); //因為private類型是不可以直接訪問的,因此需要設置訪問權(quán)限為true Test test=(Test)constructor.newInstance(new Object[]{1000}); */ Class class1=Class.forName("demo.Test"); //訪問public Test(String name,int age) // Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class}); // Test test=(Test)constructor.newInstance("陳加兵",22); //訪問默認的構(gòu)造方法 // Constructor constructor=class1.getConstructor(null); // Test test=(Test)constructor.newInstance(null); //訪問private類型的構(gòu)造方法 Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class}); constructor.setAccessible(true); Test test=(Test)constructor.newInstance(new Object[]{1000}); test.display();成員方法的操作
使用Class.getMethod()和Class.getDeclaredMethod()方法獲取方法,這兩個方法的區(qū)別前面已經(jīng)說過了,注意的是調(diào)用私有成員方法的之前一定要設置訪問權(quán)限(method.setAccessible(true))
Method類中的其他方法前面也已經(jīng)說過了,詳細使用請自己嘗試
/* * 獲取Method對象的兩種方式: * 1.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); * 2.Method method_set=class1.getMethod("set", String.class,int.class); * * * 使用Method.invoke()調(diào)用方法的兩種方式 * 1.Object o=method_set.invoke(test, new Object[]{"陳加兵",200}); * 2.Object object=method_set.invoke(test, "陳加兵",2000); */ /* * 獲取公共方法(public): * 1.Method method=class1.getMethod("display",null); //public void display() * 2.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); //獲取public void set(String name,int age) * * * 獲取私有方法(private,protected) * 1.Method method_getAge=class1.getDeclaredMethod("getAge", null); */ //使用構(gòu)造方法構(gòu)造一個Test對象 Class class1 =Class.forName("demo.Test"); Constructor成員變量的操作constructor=class1.getDeclaredConstructor(new Class[]{String.class,int.class}); Test test=constructor.newInstance(new Object[]{"陳加兵",22}); Method method=class1.getMethod("display",null); //獲取public void display()方法的Method對象 Object obj=method.invoke(test, null); //調(diào)用方法display //獲取public void set(String name,int age) // Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); Method method_set=class1.getMethod("set", String.class,int.class); // Object o=method_set.invoke(test, new Object[]{"陳加兵",200}); Object object=method_set.invoke(test, "陳加兵",2000); test.display(); //獲取私有方法private int getAge() Method method_getAge=class1.getDeclaredMethod("getAge", null); method_getAge.setAccessible(true); //必須設置訪問權(quán)限為true //判斷返回值類型是否為int類型的 if("int".equals(method_getAge.getReturnType().toString())) { int ReturnData=(int) method_getAge.invoke(test, null); //調(diào)用并且獲取返回值 System.out.println(ReturnData); }
主要使用的Field類,前面已經(jīng)詳細的說過了
/* * 獲取public修飾的成員變量: * 1.Field field=class1.getField("name"); //獲取public的成員變量name的Filed對象 * * 獲取private,protected修飾的成員變量: * 1. Field field2=class1.getDeclaredField("age"); */ Class class1=Class.forName("demo.Test"); Test test=new Test("陳加兵",1000); Field field=class1.getField("name"); //獲取public的成員變量name的Filed對象 System.out.println(field.get(test)); //獲得test對象中的name屬性的值 //獲取private int age的Field對象 Field field2=class1.getDeclaredField("age"); field2.setAccessible(true); //設置訪問權(quán)限 System.out.println(field2.get(test));參考文章
http://www.cnblogs.com/octobershiner/archive/2012/03/18/2404751.html
http://www.cnblogs.com/ixenos/p/5699420.html
https://yq.aliyun.com/wenzhang/show_17985
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70113.html
近期在維護公司項目的時候遇到一個問題,因為實體類中的 set 方法涉及到了業(yè)務邏輯,因此在給對象賦值的過程中不能夠使用 set 方法,為了實現(xiàn)功能,所以采用了反射的機制給對象屬性賦值,借此機會也了解了反射的一些具體用法和使用場景,分以下兩點對反射進行分析: 反射的優(yōu)勢和劣勢 反射的應用場景 反射的優(yōu)勢和劣勢 ??個人理解,反射機制實際上就是上帝模式,如果說方法的調(diào)用是 Java 正確的打開方式...
摘要:反射機制的應用實例在泛型為的中存放一個類型的對象。工廠模式可以參考現(xiàn)在我們利用反射機制實現(xiàn)工廠模式,可以在不修改工廠類的情況下添加任意多個子類。 學習交流群:669823128java 反射 定義 功能 示例概要:Java反射機制詳解| |目錄 1反射機制是什么 2反射機制能做什么 3反射機制的相關API 通過一個對象獲得完整的包名和類名 實例化Class類對象 獲取一個對象的父類與...
摘要:反射機制是什么反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為語言的反射機制反射機制能做什么反射機制主要提供了以下功 反射機制是什么 反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性;這種...
摘要:反射機制一結(jié)合官方通過編寫的反射教程,復習一下反射的知識。反射的概念反射是一種在運行時獲取以及修改應用行為的一種工具。因為反射需要動態(tài)的解析類的信息,相比于非反射使用的方式要慢。反射需要獲取一定的運行時權(quán)限,在特定的安全環(huán)境下不一定存在。 Java反射機制(一) 結(jié)合Oracle官方通過JDK8編寫的反射教程,復習一下反射的知識。結(jié)尾篇補一個小例子。 主要內(nèi)容 這次博客的主要內(nèi)容就是簡...
摘要:與都繼承自類,在中也是使用字符數(shù)組保存字符串,,這兩種對象都是可變的。采用字節(jié)碼的好處語言通過字節(jié)碼的方式,在一定程度上解決了傳統(tǒng)解釋型語言執(zhí)行效率低的問題,同時又保留了解釋型語言可移植的特點。 String和StringBuffer、StringBuilder的區(qū)別是什么?String為什么是不可變的? String和StringBuffer、StringBuilder的區(qū)別 可變性...
閱讀 880·2023-04-25 23:59
閱讀 3795·2021-10-08 10:04
閱讀 1711·2019-08-30 14:05
閱讀 1046·2019-08-30 13:58
閱讀 520·2019-08-29 18:41
閱讀 1149·2019-08-29 17:15
閱讀 2348·2019-08-29 14:13
閱讀 2770·2019-08-29 13:27