使用类的反射机制来访问类的私有成员变量

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







发布了25 篇原创文章 · 获赞 20 · 访问量 20万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章