Java Reflection -1 (反射機制)
Java Reflection最著名例子就是Spring,它帶來XML和Reflection的結合,可以讓開發者可以動態配置資訊、生成物件或是操過物件,何種情況需要使用Java 反射? 讓我們想一想,有些情況是否需要外部的資訊來決定程式的邏輯或是資料,或是有些情況系統之間希望保持低偶合關係。這些你都可以使用反射機制來完成,例如系統可以提供plugin的功能,來擴充系統的檢查功能,這時候可以利用反射不失為一個辦法。
Java Bean 反射範例
POJO物件 以Employee為例一個反射的對象,我們會介紹利用JAVA的反射設機制,如何將類別解析與載入內容。在一個class類架構會有: Method方法、Field屬性、Constructor建構子,如何分別解析並載入內容,是本章節的重點。
/*
* name: 員工類別的POJO
*/
public class Employee{
public Employee(String id){
this.id = id ;
}
public Employee(String id, String cname){
this.id = id ;
this.cname = cname ;
}
private String id ;
private String cname ;
private String sex ;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "id:"+id+",cname:"+cname+", sex:"+sex ;
}
}
類別反射與載入
類別反射是當我需要使用的類別時,我才做載入的動作,也稱為動態載入。如果是程式啟動時就載入,缺點比較耗資源。所以動態載入會讓系統資源更有效的運用。首先 java.lang.Class 物件代表 在運行時所載入的類別或介面實例,使用Class類別可以取得類別的資訊或是生成實例。
函式 |
說明 |
public static Class forName(String className) |
類別的對象 |
public T newInstance() |
返回一個生成實例 |
public class TestClass01 {
public static void main(String[] args) {
Class<?> c1 = Employee.class ;
System.out.println("c1-->"+c1);
try {
Class<?> c2 = Class.forName("com.tw.refleciton.Employee") ;
System.out.println("c2-->"+c2);
System.out.println("c2-->"+c2.getName());
System.out.println("c2-->"+c2.getSimpleName());
System.out.println("c2-->"+c2.getEnclosingClass());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public class TestClass02 {
public static void main(String[] args) {
try {
Class<?> c3 = Class.forName("com.tw.refleciton.Employee") ;
Object o1 = c3.newInstance() ;
System.out.println("c3-->"+c3);
System.out.println("o1-->"+o1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
// MARK Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// MARK Auto-generated catch block
e.printStackTrace();
}
}
}
建構子載入
函式 |
說明 |
Constructor[] getConstructors() |
取得該類別的建構子陣列 |
Constructor getConstructor(Class… parameterTypes) |
符合參數類別,取得建構子對象 |
T newInstance(Object… initargs) |
將內容值設定建構子並生成實例 |
/*
* name: 取得建構子資訊
*/
public class TestClass03 {
public static void main(String[] args) {
try {
Class<?> c3 = Class.forName("com.tw.refleciton.Employee") ;
Constructor<?>[] cs = c3.getConstructors();
for(Constructor<?> c : cs ){
System.out.print(c.getName()+", parameter size:"+c.getParameterTypes().length);
Class<?>[] parameters = c.getParameterTypes();
int i=1 ;
if(parameters!=null && parameters.length>0){
for(Class<?> p : parameters){
System.out.print(",parameter"+i+":"+p.getName()+" , ");
i++;
}
}
System.out.println();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
結果 |
com.tw.refleciton.Employee, parameter size:2,parameter1:java.lang.String , ,parameter2:java.lang.String , com.tw.refleciton.Employee, parameter size:1,parameter1:java.lang.String , |
/*
* name:有參數化建構子
* 利用建構子參數化宣告,必須有參數初始化建構子
*/
public class TestClass04 {
public static void main(String[] args) {
try {
Class<?> c = Class.forName("com.tw.refleciton.Employee") ;
Constructor<?> cs = c.getConstructor(String.class, String.class);
Object o = cs.newInstance("0001", "丁大幅") ;
System.out.println(o.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
// MARK Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// MARK Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// MARK Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// MARK Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// MARK Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// MARK Auto-generated catch block
e.printStackTrace();
}
}
}
結果 |
id:0001,cname:丁大幅, sex:nul |
屬性載入
函式 |
說明 |
Field[] getDeclaredFields() |
取得所有屬性 |
Field getDeclaredField(String name) |
取得指定的屬性 |
void set(Object obj, Object value) |
設定屬性的新內容值 |
Object get(Object obj) |
取得屬性的內容值 |
void setAccessible(boolean flag) |
設定該屬性是否可以訪問true: 可以訪問、false : 不可以訪問 |
boolean isAccessible() |
該屬性是否可以訪問true: 可以訪問、false : 不可以訪問 |
/**
* name:解析field的欄位名稱
*/
public class TestClass05 {
public static void main(String[] args) {
try {
Class<?> c5 = Class.forName("com.tw.refleciton.Employee") ;
Field[] fs = c5.getDeclaredFields() ;
if(fs.length>0){
for(Field f: fs){
System.out.println("field:"+f.getName());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
結果 |
name:sex,value –>> 男id:0002,cname:王大明, sex:男 |
參考
- https://github.com/JustinSDK/JavaSE6Tutorial/blob/master/docs/CH16.md
- Java反射机制连载(1)– JavaBean
- Java反射机制连载(2)– Class类
- Java反射机制连载(3)– Constructor类
- Java反射机制连载(4)– Field类
- Java反射机制连载(5)– Method类
- Java反射机制连载(6)– PropertyDescriptor类
- Java反射机制连载(7)– 使用反射实现的ORM持久层框架 attachment
- Java反射机制连载(7)– 使用反射实现的ORM持久层框架 attachment
- Java反射机制连载(9)– 自定义持久层框架之JdbcOperations接口
留言
張貼留言