反射
java反射是指在程序運行時獲取已知名稱的類或已有對象相關(guān)信息的一種機制,包括類的方法,屬性,父類等信息,還包括實列的創(chuàng)建和實列類型的判斷等
在jdk當中,主要由以下類來實現(xiàn)java反射機制,這些類都位于java.lang.reflect
1,Class類:代表著一個類
2,Constructor類:代表著類的構(gòu)造方法
3,F(xiàn)ield類:代表著類的成員變量(成員變量也成為類的屬性)
4,Method類:代表著類的方法
下面將通過代碼展示 統(tǒng)一形式解析類的構(gòu)造方法,成員變量和成員方法。
import java.lang.reflect.*;
public class A{
int m;
public A(){}
public void fun1(){}
public int fun2(){return m;}
public static void main(String[] args) throws Exception{
/**
*測試,看看是不是用mybatis連接到了數(shù)據(jù)庫
*/
bookDao bookDao=new bookDao();
System.out.println(bookDao.getBookById(1));
Class classinfo = Class.forName("A");
/**
* 以下均是獲取的結(jié)果時數(shù)組,A是自定義類,首先通過靜態(tài)方法Class.forName(“類名”)返回包含A類信息結(jié)果的Class對象
* 然后通過Class類中的getConstructors(),返回A的構(gòu)造方法信息
* getDeclaredFields()獲取相應類的成員變量信息,getDEclaredMethods()來獲取類A的成員方法信息
*/
}
注意,剛剛上面的過程僅解析lA的結(jié)構(gòu),并沒有產(chǎn)生類A的實例。以下將展示如何用反射機制產(chǎn)生A的實列呢?分別有兩種方法
2.1統(tǒng)一形式構(gòu)造函數(shù)調(diào)用方法示列
import java.lang.reflect.*;
public class test {
public test(){
System.out.println("test");
}
public test(Integer m){
System.out.println("this is m"+m);
}
public test(String S,Integer m){
System.out.println("this is S m"+S+m);
}
public static void main(String []args)throws Exception{
Class classinfo = Class.forName("test");
Constructor cons[] = classinfo.getConstructors();
for (Constructor i:cons){
System.out.println(i.toString());
}
cons[2].newInstance();
cons[1].newInstance(new Object[]{10});
cons[0].newInstance(new Object[]{"Hello",2019});
Constructor c = classinfo.getConstructor();
c.newInstance();
c = classinfo.getConstructor(new Class[]{Integer.class});
c.newInstance(new Object[]{10});
c = classinfo.getConstructor(new Class[]{String.class,Integer.class});
c.newInstance(new Object[]{"Hello",2019});
}
}
結(jié)果如下:
public test(java.lang.String,java.lang.Integer)
public test(java.lang.Integer)
public test()
test
this is m10
this is S mHello2019
test
this is m10
this is S mHello2019
1 通過Class類無參getConstructors()方法,獲取Constructor對象數(shù)組,其長度等于反射類當中實際構(gòu)造函數(shù)個數(shù),然后對這三個對象分別調(diào)用newIntance()
2 通過Class類的有參getConstrutor()方法,來獲取對應的一個構(gòu)造方法信息,然后調(diào)用newInstance()方法,完成創(chuàng)建過程。
統(tǒng)一形式調(diào)用成員方法示列
import java.lang.reflect.*;
public class test {
public test(){
System.out.println("test");
}
public test(Integer m){
System.out.println("this is m"+m);
}
public test(String S,Integer m){
System.out.println("this is S m"+S+m);
}
public void fun(){System.out.println("fun");}
public void fun1(Integer m){System.out.println("this isfun "+m);}
public void fun2(String S,Integer m){System.out.println("this is S+m"+S+m);}
public static void main(String []args)throws Exception{
Class classinfo = Class.forName("test");
Object obj = classinfo.getConstructor().newInstance();
Method mt1 = classinfo.getMethod("fun");
mt1.invoke(obj);
Method mt2 = classinfo.getMethod("fun1",Integer.class);
mt2.invoke(obj,new Object[]{10});
Method mt3 = classinfo.getMethod("fun2",String.class,Integer.class);
mt3.invoke(obj,new Object[]{"invole",2019});
}
}
結(jié)果
fun
this isfun 10
this is S+minvole2019
方法反射主要利用的是Class類的getMethod方法,得到Method對象,然后利用Method類中的invoke方法完成反射方法的執(zhí)行。
總結(jié):只要知道類名字符串,方法名字符串,方法參數(shù)值,運用反射機制就能執(zhí)行改方法。突出特點:可以把類名,方法名作為字符串變量,直接對這兩個字符串進行規(guī)范操作,就能產(chǎn)生類的實列及相應的運行方法。運用反射機制,可以大大的提高框架的穩(wěn)定程度。
反射固然強大,但是他是以犧牲實際為代價的。一般常用:接口+構(gòu)造方法反射
動態(tài)實現(xiàn)與本地實現(xiàn)相比,其運行速度要快上20倍,這是因為動態(tài)實現(xiàn)無需從java到c++再到java的轉(zhuǎn)換,而生成字節(jié)碼的時間耗時,少次使用的化,反而是本地方法要快。許多反射只會調(diào)用一次,所以jvm設置了一個閾值(15),當該反射調(diào)用次數(shù)在15次以下時,采用本地實現(xiàn)。當達到15時,便開始動態(tài)的生成字節(jié)碼,并將委派實現(xiàn)的委派對象切換至動態(tài)實現(xiàn)。這個過程我們稱為inflation
小練習
利用反射技術(shù)解析像量類java.util.Vecor有那些屬性和方法。
import java.lang.reflect.*;
public class test {
public static void main(String []args)throws Exception{
Class classinfo = Class.forName("java.util.Vector");
// 表示其構(gòu)造函數(shù)
Constructor cons[] = classinfo.getConstructors();
System.out.println("Constructor");
for (Constructor i:cons){
System.out.println(i.toString());
}
Field fil[] = classinfo.getDeclaredFields();
System.out.println("Field:");
for(Field i:fil){
System.out.println(i.toString());
}
Method met[] = classinfo.getDeclaredMethods();
System.out.println("Method");
for(Method i:met){
System.out.println(i.toString());
}
}
結(jié)果:
