首先我們來看個實例吧,一般根據Java的語法,類的私有成員變量只能被內部的方法所訪問;但是通過類的反射機制,卻可以訪問這個類的所有變量(包括私有成員變量),
我們這個實例吧。
import java.lang.reflect.Field;
public class PrivateTest1 {
/**
* @param args
*/
public static void main(String[] args)throws Exception {
PrivateTestClass1 obj =new PrivateTestClass1("leonardo"); //獲取對象
//獲取Class 對象
Class clazz =obj.getClass();
Field f =clazz.getDeclaredField("field"); //獲取類的field
//設置 私有變量可以訪問的權限
f.setAccessible(true);
//打印field的值
System.out.println(f.get(obj));
}
}
class PrivateTestClass1{
private String field;
public PrivateTestClass1(String field){
this.field =field;
}
}
這裏的關鍵是將私有變量的訪問權限改爲true 否則類的反射也是無法訪問的。
接下來我這邊要做一個拓展;是這些天面試的時候,碰到一個面試題:
能否將ReadOnlyClass 類的一個對象,把它的name屬性的值由hello改爲world?如果能,請寫出實現代碼。如果不能請說明理由。Public final class ReadOnlyClass (
private String name = “hello”;
public String getName() {
return name;
}
}
剛開始的時候 ,我竟然不加思考的回答不可以(由於該私有變量沒有set方法),可是回來仔細一想不對勁了;因爲類的反射是可以處理的。下面我們就用類的反射來解決這個問題。
import java.lang.reflect.Field;
/**
* 類反射 訪問私有變量、修改私有變量
* @author leo
*
*/
public class PrivateTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
PrivateTestClass obj =new PrivateTestClass();
Class clazz =obj.getClass(); //獲取obj對象的 class
Field f =clazz.getDeclaredField("name"); //獲取類的field
//關鍵步驟
f.setAccessible(true); //設置私有變量的可訪問性爲true
System.err.println(f.get(obj));
// ,可以同累的反射進行修改 木有set方法的 私有變量
f.set(obj, "world");
//打印出對象
System.out.println(f.get(obj));
}
}
final class PrivateTestClass{
private String name ="hello";
public String getName() {
return name;
}
}
編寫完成之後,我們進行編譯運行一下,發現打印出來的兩個 值:
hello
world
看見沒有,類的反射是可以處理該種情況,當然這種情況在我們框架中是很常見的。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
實例2:利用反射將一個bean的對象的值 封裝到map中
在寫service 層接口時,爲了讓每個接口方法的可用性更廣,我在項目中定義參數都是用一個Map<String,Object> 來定義;可是controller 傳遞過來的參數都是一個VO 的bean 對象,所以我爲了代碼可維護性更高,減少冗餘代碼,用反射寫了個工具類;
beanVO :
package com.zeng.map;
public class Student {
private String name;
private String age;
private String sex;
private String grade;
private String className;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
工具類以及測試方法:
package com.zeng.map;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 利用反射將一個bean 的對象的值封裝到Map中
* @author leo-zeng
*
*/
public class BeanUntils {
public static <T> Map<String,Object> convertBeanToMap(T t) throws Exception{
Map<String,Object> condition = new HashMap<String, Object>();
//獲取類的實例
Field[] fields = t.getClass().getDeclaredFields();
for (Field field : fields) {
//設置字段是可訪問的
field.setAccessible(true);
Object value =field.get(t);
if(value != null){
if(value instanceof String){
String _v = (String)value;
if(_v != null && _v.trim().length()>0){
condition.put(field.getName(), _v.trim());
}
}else{
condition.put(field.getName(), value);
}
}
}
return condition;
}
public static void main(String[] args) {
Student student = new Student();
student.setName("leo");
student.setAge("22");
student.setGrade("3");
try {
Map<String,Object> condition =BeanUntils.convertBeanToMap(student);
for (Map.Entry<String, Object> entry : condition.entrySet()) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
得到的測試結果是
age:22
name:leo
grade:3