Java的反射(reflection)機(jī)制是指在程序的運(yùn)行狀態(tài)中,可以構(gòu)造任意一個(gè)類的對象,可以了解任意一個(gè)對象所屬的類,可以了解任意一個(gè)類的成員變量和方法,可以調(diào)用任意一個(gè)對象的屬性和方法。這種動態(tài)獲取程序信息以及動態(tài)調(diào)用對象的功能稱為Java語言的反射機(jī)制。反射被視為動態(tài)語言的關(guān)鍵。
了解Java反射機(jī)制前先了解一下類加載器相關(guān)的知識。java文件 經(jīng)過編譯 ->Class文件(字節(jié)碼文件) 最后虛擬機(jī)執(zhí)行的就是字節(jié)碼文件, 但是字節(jié)碼文件又不會自己跑到虛擬機(jī)當(dāng)中, 這時(shí)候就得需要一個(gè)”人“,把字節(jié)碼文件放到虛擬機(jī)當(dāng)中,而這個(gè)人就是 類加載器。
類加載時(shí)機(jī)(何時(shí)加載字節(jié)碼文件):
總結(jié):用到就加載,不用不加載
類加載過程
驗(yàn)證
準(zhǔn)備
解析
解析過程拆解:
name的類型是引用類型(String),String是其他的類的名字,最初加載String類的時(shí)候不知道String類在哪里,這時(shí)的String使用符號(ex:&&&)替代。在解析的過程中,就會找實(shí)際的String類在哪里,并把臨時(shí)的符號變成實(shí)際的String引用
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 獲取系統(tǒng)類加載器的父類加載器,平臺類加載器
ClassLoader clasLoader1 = systemClassLoader.getParent();
//獲取平臺類加載器的父類加載器, 啟動類加載器
ClassLoader classLoader2 = clasLoader1.getParent();
System.out.println("系統(tǒng)類加載器" + systemClassLoader);
System.out.println("平臺類加載器" + clasLoader1);
System.out.println("啟動類加載器" + classLoader2);
1.4 雙親委派模型方法名 | 說明 |
---|---|
public static ClassLoader getSystemClassLoader() | 獲取系統(tǒng)類加載器 |
public InputStream getResourceAsStream(String name) | 加載某一個(gè)資源文件 |
//獲得系統(tǒng)類加載器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 利用類加載器去加載一個(gè)指定的文件
// 參數(shù):文件的路徑
// 返回值:字節(jié)流
// 這里直接填寫prop.properties,相對的在src下邊
InputStream resourceAsStream = systemClassLoader.getResourceAsStream("prop.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
System.out.println(properties);
resourceAsStream.close();
2. 反射
2.1 反射的概述Java反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類所有的屬性與方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意屬性和方法(利用反射調(diào)用它類中的屬性和方法時(shí),無視修飾符)。
這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為Java語言的反射機(jī)制(先獲取配置文件中的信息,動態(tài)獲取信息并創(chuàng)建對象和調(diào)用方法)
public class Student {private String name;
private int age;
public Student() {}
public Student(String name, int age) {this.name = name;
this.age = age;
}
public String getName() {return name;
}
public void setName(String name) {this.name = name;
}
public int getAge() {return age;
}
public void setAge(int age) {this.age = age;
}
public void study(){System.out.println("學(xué)生在學(xué)習(xí)");
}
@Override
public String toString() {return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Class>clazz = Class.forName("全類名");
Classclazz2 = Student.class;
Student s = new Student();
//每一個(gè)對象都對應(yīng)著一個(gè)字節(jié)碼文件,所以getClass方法是定義在Object中的
Class clazz3 = s.getClass();
System.out.println(clazz == clazz2);//true
System.out.println(clazz3 == clazz2);//true
2.3 獲取Class類對象中的內(nèi)容Java當(dāng)中什么都可以看成一個(gè)對象,只要是對象,就可以用類去描述。從class類中獲取的成員變量就可以把它認(rèn)為是成員變量對象(Field),以此類推…
如何學(xué)習(xí)?
大概步驟(以獲取構(gòu)造方法為例)
-獲取class對象
-獲得Constructor對象
-創(chuàng)建對象
明白幾個(gè)問題
-獲取對象不就是為了創(chuàng)建對象么?
-獲取屬性不就是為了給他賦值和取值么?
-獲取方法不就是為了調(diào)用么?
學(xué)習(xí)
-把整個(gè)流程以及為什么用反射了解清楚,方法忘了就去api手冊查,重復(fù)多了自然也就記住了
總結(jié)
-先獲取整體(Class對象),在獲取部分(成員屬性,構(gòu)造方法,成員男方法),然后操作部分
如圖所示:Class對象加載到內(nèi)存當(dāng)中,我們可以去獲取想要的信息
方法名 | 說明 |
---|---|
Constructor>[] getConstructors() | 返回所有公共構(gòu)造方法對象的數(shù)組 |
Constructor>[] getDeclaredConstructors() | 返回所有構(gòu)造方法對象的數(shù)組 |
Constructor getConstructor(Class>… parameterTypes) | 返回單個(gè)公共構(gòu)造方法對象 |
Constructor getDeclaredConstructor(Class>… parameterTypes) | 返回單個(gè)構(gòu)造方法對象 |
public class Student {private String name;
private int age;
public String getName() {return name;
}
public void setName(String name) {this.name = name;
}
public int getAge() {return age;
}
public void setAge(int age) {this.age = age;
}
public void study() {System.out.println("我的名字是:" + name);
System.out.println("學(xué)生在打籃球");
}
private Student(String name) {System.out.println("name的值為:" + name + "age的值為:" + age);
System.out.println("private ... student ... 有參構(gòu)造方法");
}
public Student() {System.out.println("public ... student ... 無參構(gòu)造方法");
}
public Student(String name, int age) {System.out.println("name的值為:" + name + "age的值為:" + age);
System.out.println("public ... student ... 有參構(gòu)造方法");
}
@Override
public String toString() {return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
main
private static void method4() throws ClassNotFoundException, NoSuchMethodException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//小括號中一定要和構(gòu)造方法的形參保持一致
Constructor>constructor = clazz.getConstructor();
System.out.println(constructor);
Constructor>constructor2 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor2);
//會報(bào)錯,沒有形參為int的構(gòu)造方法
Constructor>constructor3 = clazz.getConstructor(int.class);
System.out.println(constructor3);
}
private static void method2() throws ClassNotFoundException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor>declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);
}
}
private static void method1() throws ClassNotFoundException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>[] constructors = clazz.getConstructors();
for (Constructor>constructor : constructors) {System.out.println(constructor);
}
}
2.4.2 通過Constructor對象中的方法創(chuàng)建對象方法名 | 說明 |
---|---|
T newInstance(Object…initargs) | 根據(jù)指定的構(gòu)造方法創(chuàng)建對象 |
setAccessible(boolean flag) | 設(shè)置為true,表示取消訪問檢查 |
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {// method1();
// method2();
// method3();
//獲取一個(gè)私有的構(gòu)造方法,并創(chuàng)建對象
//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//2.獲取一個(gè)私有化的構(gòu)造方法
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//被private修飾的成員,不能直接使用
//如果使用反射前行獲取并使用,需要臨時(shí)取消訪問檢查
constructor.setAccessible(true);
//3.直接創(chuàng)建對象
Student student = (Student) constructor.newInstance("李白");
System.out.println(student);
}
private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException { //簡寫格式
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Student student = (Student) clazz.newInstance();//這個(gè)方法過時(shí)了
}
private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>constructor = clazz.getConstructor();
Student student = (Student) constructor.newInstance();
System.out.println(student);
}
private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { // 獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//獲取構(gòu)造方法對象
Constructor>constructor = clazz.getConstructor(String.class, int.class);
//利用newInstance方法,創(chuàng)建Student對象
Student student = (Student) constructor.newInstance("李白", 61);
System.out.println(student);
}
2.4.3 小結(jié)方法名 | 說明 |
---|---|
Field[] getFields() | 返回所有公共(public)成員變量對象的數(shù)組 |
Field[] getDeclaredFields() | 返回所有成員變量對象的數(shù)組 |
Field getField(String name) | 返回單個(gè)公共成員變量對象 |
Field getDeclaredField(String name) | 返回單個(gè)成員變量對象 |
private static void method4() throws ClassNotFoundException, NoSuchFieldException {//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取name這個(gè)成員變量
Field field = clazz.getDeclaredField("money");
//3.打印
System.out.println(field);
}
private static void method3() throws ClassNotFoundException, NoSuchFieldException {//想要獲取的成員變量必須是真是存在的,且是public的
//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取name這個(gè)成員變量
Field field = clazz.getField("money");
//3.打印
System.out.println(field);
}
private static void method2() throws ClassNotFoundException {//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取Field對象
Field[] fields = clazz.getDeclaredFields();
//3.遍歷
for (Field field : fields) {System.out.println(field);
}
}
private static void method1() throws ClassNotFoundException {//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取Field對象
Field[] fields = clazz.getFields();
//3.遍歷
for (Field field : fields) {System.out.println(field);
}
}
2.5.2 給成員變量賦值方法名 | 說明 |
---|---|
void set(Object obj, Object value) | 賦值 |
Object get(Object obj) | 獲取值 |
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {// method1();
//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取成員變量的Field對象
Field field = clazz.getDeclaredField("money");
//3.取消訪問檢查
field.setAccessible(true);
//4.調(diào)用get方法來取值
//4.1創(chuàng)建一個(gè)對象
Person person = (Person) clazz.newInstance();
//4.2獲取指定對象的money的值
Object o = field.get(person);
//5.打印
System.out.println(o);
}
private static void method1() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
// 2.獲取name這個(gè)Field對象
Field field = clazz.getField("name");
//3.利用set方法進(jìn)行賦值
//3.1先創(chuàng)建一個(gè)Student對象
Person person = (Person) clazz.newInstance();
//3.2有了對象才可以給指定對象賦值
field.set(person,"李白");
System.out.println(person);
}
2.6 反射獲取成員方法并使用
2.6.1 Class類獲取成員方法對象的方法方法名 | |
---|---|
Method[] getMethods() | 返回所有公共成員方法對象的數(shù)組,包括繼承的 |
Method[] getDeclaredMethods() | 返回所有成員方法對象的數(shù)組,不包括繼承的 |
Method getMethod(String name, Class>… parameterTypes) | 返回單個(gè)公共成員方法對象 |
Method getDeclaredMethod(String name, Class>… parameterTypes) | 返回單個(gè)成員方法對象 |
private static void method5() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取私有的方法
Method look = clazz.getDeclaredMethod("look");
System.out.println(look);
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取有形參的方法
Method method1 = clazz.getMethod("method2", String.class);
System.out.println(method1);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取無參數(shù)的方法
Method method1 = clazz.getMethod("method1");
System.out.println(method1);
}
private static void method2() throws ClassNotFoundException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取成員方法對象
Method[] methods = clazz.getDeclaredMethods();// 返回所有成員方法的數(shù)組,不包含繼承的
for (Method method : methods) {System.out.println(method);
}
}
private static void method1() throws ClassNotFoundException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取成員方法對象
Method[] methods = clazz.getMethods();// 繼承父類的方法也在里邊
for (Method method : methods) {System.out.println(method);
}
}
以上就是今天要講的內(nèi)容,本文僅僅簡單介紹了Java的反射機(jī)制,因?yàn)橛嘘P(guān)反射的方法眾多,本文只介紹了較為常用的一些去供大家學(xué)習(xí)和了解!
本文中的案例大家不要光看哦,試著放到程序中運(yùn)行一下,對加深理解有很大的幫助的!
最后,創(chuàng)作不易,如果本文對您有一點(diǎn)幫助的話,就點(diǎn)贊、收藏、關(guān)注支持鼓勵一下吧,您的支持是我創(chuàng)作的動力!
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
本文題目:Java反射-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://muchs.cn/article42/phchc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站改版、動態(tài)網(wǎng)站、網(wǎng)站排名、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容