概念
JAVA反射機(jī)制是指在運(yùn)行狀態(tài)中雄人,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;
對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性拷邢;
這種動態(tài)獲取信息以及動態(tài)調(diào)用對象的方法的功能稱為JAVA語言的反射機(jī)制
Class類
- 區(qū)別于class關(guān)鍵字
- Class類的實(shí)例表示正在運(yùn)行的Java應(yīng)用程序中的類和接口祖乳,JVM中每個(gè)類都有該Class對象(括基本數(shù)據(jù)類型)
- Class沒有公共構(gòu)造方法日缨,Class對象是在加載類時(shí)由虛擬機(jī)以及通過調(diào)用類加載器中的defineClass方法自動構(gòu)造的
反射的使用
- 一般用一個(gè)清單文件記錄所有要通過反射加載的類声搁,程序內(nèi)讀取清單文件加載類
獲取Class對象
- Object里面提供的方法
getClass()
- 任何數(shù)據(jù)類型(包括基本數(shù)據(jù)類型)都有一個(gè)“靜態(tài)”的class屬性
- 通過Class類的靜態(tài)方法
forName(String className)
(常用)
Class class1 = Class.forName(className);// 從path內(nèi)查找class加載,不能指定路徑
- 通過ClassLoader獲仁偾础(常用)
通過反射獲取構(gòu)造方法
getConstructor(Class<?>... parameterTypes)
返回一個(gè)Constructor對象锁右,它反映此Class對象所表示的類的指定公共構(gòu)造方法
getConstructors()
返回一個(gè)包含某些Constructor對象的數(shù)組,這些對象反映此Class對象所表示的類的所有公共構(gòu)造方法
通過反射獲取成員變量
getField(String name)
返回一個(gè)Field對象讶泰,它反映此Class對象所表示的類或接口的指定公共成員字段
getFields()
返回一個(gè)包含某些Field對象的數(shù)組咏瑟,這些對象反映此Class對象所表示的類或接口的所有可訪問公共字段
通過反射獲取成員方法
getMethod(String name, Class<?>... parameterTypes)
返回一個(gè)Method對象,它反映此Class對象所表示的類或接口的指定公共成員方法
getMethods()
返回一個(gè)包含某些Method對象的數(shù)組峻厚,這些對象反映此Class對象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共member方法
拓展實(shí)例
- 從指定路徑的class文件獲取類(文件名可自定義)
- 通常是獲取清單文件得到路徑及包名
- 實(shí)現(xiàn)方法是重寫ClassLoader的findClass方法
- 被調(diào)用class必須實(shí)現(xiàn)Access接口(一個(gè)指定的接口响蕴,用于降低耦合性)
public class FileClassLoader extends ClassLoader {
private File classFile;
public FileClassLoader(File classFile) {
super();
this.classFile = classFile;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] classData = loadClassData();
return defineClass(name, classData, 0, classData.length);// 通過defineClass方法將類的字節(jié)加載為類
} catch (IOException e) {
throw new ClassNotFoundException();// IO異常則為類找不到
}
}
/**
* 從文件讀取類字節(jié)
*
* @return 類文件的字節(jié)數(shù)組
* @throws IOException
*/
private byte[] loadClassData() throws IOException {
final int SIZE = 1024;
byte[] bytes;
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(classFile))) {
ByteArrayOutputStream outWriter = new ByteArrayOutputStream();
byte[] buf = new byte[SIZE];
int len;
while ((len = bis.read(buf)) != -1) {
outWriter.write(buf, 0, len);
}
outWriter.flush();
bytes = outWriter.toByteArray();
}
return bytes;
}
}
接口(被調(diào)用的類必須實(shí)現(xiàn)這個(gè)接口)
package reflect;
public interface Access {
public <T> void method1(T parameter1);
public <T> void method2(T parameter1, T parameter2);
}
調(diào)用方法
FileClassLoader fileClassLoader = new FileClassLoader(new File("I:\\JAVA_Project\\Test.class"));// 文件名可自定義
Class<?> acsClass = fileClassLoader.loadClass("reflect.Test");// 包名
Access acs = (Access) acsClass.newInstance();// 被調(diào)用class必須實(shí)現(xiàn)Access接口
acs.method1("測試打印");// 調(diào)用方法