一,反射的概念
對于一個人來說,了解自己的能力、本事、特點,對于他去干事創業來說,是很重要的。
同樣的,對于一門面向對象的語言來說,了解類(對象其實就是類的實現)本身也是重要的,可以在很多地方幫助程序更好的進行。
那么類/對象本身包含那些內容呢,無非就是類名稱;父類;繼承的接口;類的屬性;類的方法,這些都屬于是類的信息。
好的,那么這些信息程序員都知道啊,類的信息在定義類的時候不是都寫的明明白白的嗎。但是反射的意義卻是:在程序跑起來之后可以使用代碼去獲取類的信息。這個,沒有反射可辦不到。
Java是面向對象的,所有的東西都是有類別的。所以哦,類的信息也是一種類型(就像用戶信息可以用UserInfo類描述),類的信息對應的Java類為Class類,注意不是關鍵字class哈。
舉個最常見的栗子:
public class ClassDemo {
public static void main(String[] args) {
try {
Class mysqlDriver=Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
這里Class.forName很明顯是Class類的一個static方法,這個方法的意思就是按類名(完整的帶包路徑的類名)返回類對應的Class對象。因為forName的參數是可以隨便寫的嘛,所以會拋出一個ClassNotFoundException。
Class.forName方法是在程序運行時按類名稱獲取類的信息的方法,這就是反射機制。
二,如何獲取類的Class對象
我們定義一個普通類Student,可以有三種方式獲取到Student的類型信息:
package temp;
public class Student {
String studentName;
public String getStudentName(){
return studentName;
}
public static void main(String[] args) throws ClassNotFoundException {
//方式1 利用類名稱
Class class1 = Class.forName("temp.Student");
//方式2 利用類
Class class2=Student.class;
//方式3 利用對象
Student student=new Student();
Class class3=student.getClass();
}
}
三,通過類的Class對象獲取類的屬性和方法
獲取到Class(類的類型)之后,再獲取屬性和方法就簡單了,直接使用Class類封裝的方法即可。
getDeclaredFields:獲取類屬性
getDeclaredMethods():獲取類方法
使用一個完整的程序演示如下:
package temp;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Student {
String studentName;
public String getStudentName(){
return studentName;
}
public static void main(String[] args) throws ClassNotFoundException {
Class classStu=Student.class;
Field[] fields = classStu.getDeclaredFields();
for(Field field:fields){
System.out.println("屬性類型:"+field.getType().getSimpleName()+",屬性名稱:"+field.getName());
}
Method[] methods=classStu.getDeclaredMethods();
for(Method method:methods){
System.out.println("方法名稱:"+method.getName()+",返回類型"+method.getReturnType());
}
}
}
執行結果如下:
屬性類型:String,屬性名稱:studentName
方法名稱:main,返回類型void
方法名稱:getStudentName,返回類型class java.lang.String
可見,通過Class類封裝的方法,可以在程序運行時候直接獲取類的信息。
四,反射的意義
凡是都有正反兩個方面,先說不好的消息吧,用了反射,性能肯定是會降低的。注意此處的性能低,并不是說通過反射獲取類的信息性能低,因為除了反射也沒有啥可以獲取類的信息的機制了。
性能低是指通過反射調用方法性能低,看下面的例子,通過反射獲取到方法之后,可以將該方法應用到一個對象上實現該對象的方法調用。本來可以直接調用,反射之后再調用肯定效率要低的。
Class classStu=Student.class;
Student student=new Student();
Method methodGet=classStu.getDeclaredMethod("getStudentName");
//可以通過Method類的invoke方法調用類方法,當然必須得提供對象
String name=(String)methodGet.invoke(student);
System.out.println(name);
但是反射的正面意義還是光輝的,首先提供了一種了解類的信息的手段,使程序運行編寫、運行更加自由靈活,充滿了更多可能性。
簡單的想,在將對象轉換為json時,鍵值對的鍵不就是對象的屬性名稱么,用反射獲取對象的屬性名稱是多么爽快的事情啊。