首先我们来看个实例吧,一般根据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