我們先來看反射提供的功能:
反射機制提供功能:加載運作時确定資料類型,解析類結構,擷取内部資訊
操作該類型或執行個體,通路屬性,調用方法,建立新對象
java反射是誰來提供呢?
Class對象提供,但是首先需要通過JVM擷取對象,建立Class對象
建立Class對象有三種方式:
使用Class類的forName()靜态方法如:Class.forName(java.lang.reflect.Field)
調用類的class屬性擷取對應的Class對象,
調用某個對象的getClass()方法
擷取Class對象,就可以得到對象的真實資訊
如:對象的構造函數,屬性,方法,注解,接口,父類,注解(必須是具有源碼,否則注解不能查詢到)等
如:
Constructor<?>getconstructors()傳回class對象辨別的所有public 構造器
Method[] getMethods()
FieldgetField(String name)
Annotation[]getAnnotations()
以上方法是有多重載的,可根據參數類型擷取不同如 class.getMethod("info",String.class)
反射能做什麼?
以上是通過反射擷取對象,取得對象的屬性方法
同時反射還可以生成對象以及操作對象的方法,形成動态代理的基礎,ORM的基礎
建立對象方式
使用Class對象newIntance()建立class對象執行個體,但必須有預設構造器
或使用class對象指定的構造器,再調用newInstance方法,可以建立指定執行個體
事例
擷取某個對象,并建立該對象調用該對象方法
1 POJO類
public class User {
private String userName;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public User(){
}
public User(String username){
this.userName=username;
}
2 調用類與執行個體
public static void main(String[] args) throws SecurityException,
NoSuchFieldException, InstantiationException, IllegalAccessException,
NoSuchMethodException, ClassNotFoundException {
getProperty(User.class);//調用
}
public static void getProperty(Class<?> entityClass) throws SecurityException,
NoSuchFieldException, InstantiationException, IllegalAccessException,
NoSuchMethodException, ClassNotFoundException {
//-----start----反射擷取對象---------
String cName = entityClass.getName();
// 從類的名字中解析出類名
String userName = cName.substring(cName.lastIndexOf(".") + 1, cName.length());
System.out.println("實體名稱為:"+ userName);
// 擷取對象的所有屬性
Field[] fields = entityClass.getDeclaredFields();
// 擷取對象的所有方法
Method[] methods = entityClass.getDeclaredMethods();
List<String> listfeld = new ArrayList<>();
for (Field field : fields) {
System.out.println("屬性名稱有:" + field.getName());
}
for (Method method : methods) {
System.out.println("方法名稱有:" + method.getName());
}
//-------反射擷取對象-end--------+
//反射建立對象,調用對象方法-------start--------
User userfroname = (User) Class.forName(cName).newInstance(); //擷取Class對象方式1 :通過字元串
User userClass = (User) entityClass.newInstance(); //擷取Class對象方式2: 通過Class類型
userClass.setUserName("我的大名是:任秋明---通過class名稱建立對象");
userfroname.setUserName("我的大名是:任秋明--Class類型建立對象");
System.out.println(userClass.getUserName());
System.out.println(userfroname.getUserName());
//反射建立對象,調用對象方法-------end--------
}
3 測試結果
實體名稱為:User
屬性名稱有:userName
屬性名稱有:password
方法名稱有:getUserName
方法名稱有:setUserName
方法名稱有:setPassword
方法名稱有:getPassword
我的大名是:任秋明---通過class名稱建立對象
我的大名是:任秋明--Class類型建立對象
小結:
總的來說,java反射機制可以解決一些不靈活的程式,IOC的依賴注入,動态代理,動過名稱反射調用類的方法。但與此同時反射同時也帶來的效率上的問題,凡事都有兩面性,要靈活難免犧牲效率。