引言:java的高級特性-反射一直是困擾自己的一個很大問題肛响,今天專門花了半天再將java中的反射看了一遍,下面簡單談?wù)勛约簩Ψ瓷涞睦斫猓约八木唧w用法:
一:什么是反射?
- 在java核心編程中是這樣定義的:能夠分析類能力的程序橱脸;
public class fruit{
private String name;
public fruit(String name){
this.name = name;
}
public void getName(){
return name;
}
public String setName(String name){
this.name = name;
}
public static void main(String[] args){
fruit apple =new fruit();
apple.getName();
}
}
按照J(rèn)ava創(chuàng)建對象的正常邏輯,如上面的代碼所示分苇,我們一般都是根據(jù)具體的類fruit來創(chuàng)建對象apple,然后在利用我們所創(chuàng)建的對象去調(diào)用方法添诉;apple.getName();而java中的反射的流程則相反是根據(jù)具體的對象去獲取相關(guān)的類Class的信息,
二:反射的作用:
- <1>:可以在程序運行過程中分析類的能力
- <2>:在運行中查看對象医寿,例如編寫一個toString方法供所有類使用
- <3>:實現(xiàn)數(shù)組的操作代碼
- <4>:利用Method對象栏赴;
三:具體怎么使用:
補(bǔ)充知識:我們都知道,編寫java程序時我們所編寫的文件是一個名為xxx.java的文件靖秩,通過java編譯器編譯之后會成為一個.class文件须眷;這時再通過JVM的類加載器加載到JVM的運行時數(shù)據(jù)區(qū)里面的方法區(qū)(.class)文件,所謂方法區(qū)里面保存的類的相關(guān)信息就是指這一過程的產(chǎn)生的class對象沟突;
java程序在運行過程中會為每一對象保存一個Class對象花颗,用來保存該對象和類的一些相關(guān)信息;比如:方法惠拭,屬性扩劝,構(gòu)造函數(shù)等;所以想要使用反射我們首先要做的就是拿到Class對象求橄;
- <1>:拿到Class對象:
有三種方法: - A:根據(jù)對象獲取的getClass()方法:
Class cls = apple.getClass();
B:根據(jù)類的class屬性獲取
Class cls = fruit.class;
C:根據(jù)Class類的靜態(tài)方法forName("類的完整路徑")
Class cls = Class.forName("Chapter1.fruit")
具體采用那一種今野,大家可以根據(jù)具體情況具體分析;
- <2>:根據(jù)拿到的Class對象創(chuàng)建我們所需的對象:
fruit orange = (fruit)cls.newInstance();//注意該方法返回的Object對
象罐农,所以我們需要強(qiáng)制類型轉(zhuǎn)換条霜;
這里創(chuàng)建對象調(diào)用的是fruit類中的默認(rèn)的構(gòu)造方法,如果沒有默認(rèn)構(gòu)造方法此項操作將會報錯已檢查異常(即運行時會報錯)涵亏;
所以我們調(diào)用此方法時一定要保證目標(biāo)類有默認(rèn)的構(gòu)造方法宰睡;
- <3>:獲取調(diào)用構(gòu)造方法:
Constructor con = cls.getConstructor(Class<?>... parameterTypes)//返回指定采參數(shù)類型的構(gòu)造方法;注意參數(shù)一定要傳遞Class對象哦气筋!
Constructor[] con = cls.getConstructors();//返回所有的共有構(gòu)造器:構(gòu)造方法數(shù)組拆内;
Constructor[] con = cls.getDeclaredConstructors();//返回所有的構(gòu)造器:構(gòu)造方法數(shù)組;
Constructor con = cls.getDeclaredConstructor(Class<?>... parameterTypes);//返回指定的構(gòu)造器:構(gòu)造方法數(shù)組宠默;
//在拿到對應(yīng)的都早方法之后我們就可以根據(jù)指定構(gòu)造方法創(chuàng)建對象
Constructor cons = cls.getConstructor(String.class);
fruit f = cons.newInstance("陳鵬");
- <4>:獲得調(diào)用普通方法
Method[] methods = cls.getMethods();//返回該類中以及其超類中所有的的公有的方法
Method[] methods = cls.getDeclaredMethods();//返回該類中所有的的公有的方法,不包括從超類中繼承而來的方法
Method method = cls.getMethod(String name, Class<?>... parameterTypes)//返回指定的方法這里的name是方法名麸恍,parameterTypes表示參數(shù)列表
Method method = cls.getMethod("getName",String.class);
method.invoke(Object obj, Object... args);//這里的obj表示的調(diào)用該方法的對象,后面的args是參數(shù)列表;
關(guān)于invoke方法:第一個參數(shù)是隱式參數(shù)(this)第二個參數(shù)是顯示參數(shù)抹沪,(java SE 5.0之前)必須傳遞一個數(shù)組對象刻肄,如果沒有顯示參數(shù)可以將傳遞一個null;如果是靜態(tài)方法可以將第一參數(shù)忽略即將其設(shè)置為null;
- <5>:訪問域(屬性)
Field field = cls.getFiled(String name);//返回聲明在該類或其其超類中的指定的共有域
Field[] fields = cls.getFileds();//返回所有的聲明在該類以及其超類中的共有域
Field field = cls.getDeclaredFiled(String name);//返回所有的聲明在該類中的共有域融欧;
Field[] fields = cls.getDeclaredFileds();//返回所有的聲明在該類中的共有域敏弃;
Field field = cls.getDeclaredField("name");
ps一般情況下我們的私有屬性是不可以進(jìn)行訪問,但java的反射也可以讓我們訪問到私有屬性:
//通過調(diào)用下面方法表可將私有屬性設(shè)置為可以訪問的
Field.setAccessable(true)
補(bǔ)充例子1:使用Java的反射獲取泛型信息:
class Person<T>{
public Person(){
//Type[] cls = ((ParameterizedType)(this.getClass().getGenericSuperclass())).getActualTypeArguments();
//獲取父類的子類傳遞過來的類型
Type type= this.getClass().getGenericSuperclass();
//轉(zhuǎn)換成對應(yīng)的參數(shù)類型
ParameterizedType rtype =(ParameterizedType)type;
Type[] types = rtype.getActualTypeArguments();
for(Type t:types){
System.out.println(((Class)t).getName());
}
}
}
class Student extends Person<String>{
public Student(){
System.out.println("我是子類的構(gòu)造方法噪馏!");
}
}
這里注意:調(diào)用子類構(gòu)造器之前會先調(diào)用父類的構(gòu)造器麦到;
補(bǔ)充例子2:使用反射回去注解信息:
反射注解
- 要求
- 注解的保留策略必須是RUNTIME(有三種狀態(tài):RESOURCE,CLASS,RUNTIME)
- 反射注解需要從作用目標(biāo)上返回
- 類上的注解,需要使用Class來獲取
- 方法上的注解欠肾,需要Method來獲取
- 構(gòu)造器上的注解瓶颠,需要Construcator來獲取
- 成員上的,需要使用Field來獲取
Class
Method董济、Constructor步清、Field:這三個類都實現(xiàn)了:AccessibleObject類
它們都有一個方法:
- Annotation getAnnotation(Class),返回目標(biāo)上指定類型的注解虏肾!
- Annotation[] getAnnotations()廓啊,返回目標(biāo)上所有注解!
總結(jié):以上就是自己關(guān)于java反射方面的簡單的理解封豪,如果內(nèi)容有出錯的地方望大家及時指正谴轮,謝謝!