Java之反射与单级VO操作

在讲关于反射与单级VO操作之前,我们先来看一个问题:

要求:在主方法中将指定类(该类中构造方法只有无参构造)的所有属性设置指定的值,我们传统的做法如下所示:

(1)定义一个类,假设该类含有两个属性,该类中也定义了各属性对应的的setter()和getter()方法

(2)在主方法中,通过实例化类对象利用setter()和getter()方法将两个属性值进行设置

(3)根据(1)(2)步所讲,编写代码如下所示:

class Person{
	private String name;
	private String job;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
}
public class Test {
	public static void main(String[] args) {
		Person person=new Person();
		person.setName("张三");
		person.setJob("程序员");
		System.out.println(person.getName());
		System.out.println(person.getJob());
	}
}

运行结果如下所示:

张三
程序员

那么问题来了:假设一个类(如Person类)中存在十几个甚至更多的属性,那么依据以上代码就需要在主方法中调用十几次甚至更多次的setter()方法,这样的操作太过麻烦!

现在希望能够对程序做简化,输入字符串"属性名:属性值|属性名:属性值|属性名:属性值|...",将某个类中的属性值一次设置好。那么既然是编写程序将某个类进行一次设置好其所有属性的值,那么能不能将任意类中的所有属性通过输入字符串"类名.属性名:属性值|类名.属性名:属性值|类名.属性名:属性值|..."设置好其对应类的所有属性值呢?

这就需要反射实现该操作!

下面我带大家一起来分析整个程序设计的思路:

(1)由于字符串传入的入口是主类(如Test)中的主方法,为了对主方法与具体类(如Emp)进行解耦,故使用一个第三方类(如EmpAction)实现解耦问题。

(2)接着考虑第三方类(如EmpAction)的设计,该类主要实现通过调用一个类似于setter()方法从而对传入的字符串对应的属性进行设置。并且为了在反射操作中的使用,在该类中需要实例化具体类(如Emp)的对象。

(3)我们真正要做的事是将字符串中的内容进行设置,这是一个独立的操作。故为了实现第三方类(EmpAction)与实现具体操作的方法(即设置属性值)之间的解耦问题,故又引入一个类(如BeanOperation),该类(BeanOperation)主要通过反射实现字符串内容到具体类(Emp)的所有属性的值的设置。

总结一下以上的分析:需要四个类:主类(Test类)、具体类(Emp类)、实现主方法与具体类解耦的第三方类(EmpAction类)以及第三方类和真正操作的方法实现解耦的工具类(BeanOperation类)。

下面实现代码:

(1)具体类(Emp类):

该类定义所需要的所有属性,以及各属性对应的setter()和getter()方法,并且覆写toString()方法(为了方便查看之后查看是否设置成功),故Emp类的代码如下所示:

package www.bit.java.vo;
/**
 * 一个简单Java类,包含两个属性以及它们的getter方法、setter方法并覆写了toString方法
 * @author Administrator
 *
 */
public class Emp {
	private String name;
	private String job;
	public String getName() { 
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	@Override
	public String toString() {
		return "Emp [name=" + name + ", job=" + job + "]";
	}
}

(2)第三方类(EmpAction类):

该类需要实例化具体类Emp类的对象,用于反射操作中的使用;定义一个方法用于接收在主方法中传入的字符串,在该方法中调用实现解耦的BeanOperation类的一个方法,从而利用BeanOperation类中的方法操作该字符串;再定义一个方法用于通过反射取得Emp类对象以及打印具体类Emp类的对象从而判断是否将各属性设置成功。代码如下所示:

package www.bit.java.vo;

import www.bit.java.util.BeanOperation;

/**
 * 该类相当于第三方类,实现了真正类与主方法的解耦
 */
public class EmpAction {
	//实例化具体类Emp类的对象,用于反射操作的使用
	private Emp emp=new Emp();
	//定义getEmp()方法,用于反射取得emp对象以及在主方法中检测是否将各属性值设置进去
	public Emp getEmp() {
		return emp;
	}
	//定义setValue()方法,用于在主方法中接收字符串内容,从而设置属性值
	public void setValue(String value) throws Exception{
		//调用BeanOperation类的方法setValueReal()方法,真正实现字符串内容到各属性值设置的操作
		BeanOperation.setValueReal(this,value);
	}
}

(3)主类(Test类):

该类中的主方法通过实例化第三方类EmpAction类的对象,从而调用EmpAction类的用于接收字符串的方法,代码如下所示:

package www.bit.java.vo;

public class Test {
	public static void main(String[] args) throws Exception{
		String value="emp.name:xieguangtao|emp.job:student";
		//实例化EmpAction类的对象
		EmpAction empAction=new EmpAction();
		//调用EmpAction类的setValue()方法,从而传入字符串内容
		empAction.setValue(value);
		//调用EmpAction类的getEmp()方法,用于检测是否将各属性值设置进去
		System.out.println(empAction.getEmp());
	}
}

(4)工具类(BeanOperation类):

该类用于真正实现字符串内容到各属性值设置的操作的类,该类的具体操作在代码中有详细的注释,代码如下所示:

package www.bit.java.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class BeanOperation {
	/**
	 * 由于它只是工具类,不需要实例化,故将构造方法私有化
	 */
	private BeanOperation() {};
	/**
	 * 实现根据字符串设置属性的方法
	 * @param obj表示调用该方法的对象
	 * @param value表示在Test类中传入的字符串,格式为:类.属性名:属性值|类.属性名:属性值
	 */
	public static void setValueReal(Object obj,String value) throws Exception{
		/**
		 * 1.将字符串进行拆分,便于操作!
		 */
		//(1)按照|拆分,从而拆分后的格式为:类.属性名:属性值
		String[] value1=value.split("\\|");
		//(2)按照:拆分,从而拆分后的格式为:类.属性名    属性值
		for(int i=0;i<value1.length;i++) {
			String[] value2=value1[i].split(":");
			//(3)按照.拆分,从而拆分后的格式为:类    属性名
			String[] value3=value2[0].split("\\.");
			//(4)分别标记类、属性名、属性值
			String myClass=value3[0];
			String myField=value3[1];
			String myValue=value2[1];
			/**
			 * 2.利用拆分得到的类名,通过反射调用EmpAction类中的getEmp方法取得Emp类的对象emp
			 */
			Object object=getClassObject(obj,myClass);
			/**
			 * 3.利用得到的Emp类的对象emp,通过反射获取Emp类的setter方法进行属性设置
			 */
			setValueObject(object,myField,myValue);	
		}
	}
	/**
	 * 将给定字符串的首字母大写
	 * @param 给定的字符串
	 * @return 首字母大写的字符串
	 */
	public static String myFirstUpper(String str) {
		return str.substring(0,1).toUpperCase()+str.substring(1);
	}
	/**
	 * 调用EmpAction类中的getEmp方法取得Emp类的对象emp
	 * @param obj表示调用该方法所在类的对象
	 * @param myClass表示拆分字符串得到的类名emp
	 * @return 返回通过反射调用EmpAction类的getEmp方法得到的私有属性emp,即Emp类的对象
	 */
	public static Object getClassObject(Object obj,String myClass) throws Exception{
		//1.获取反射需要调用的方法名
		String methodName="get"+myFirstUpper(myClass);
		//2.判断传入的类名对应的对象是否在当前类中存在,若不存在则直接return
		Field field=obj.getClass().getDeclaredField(myClass);
		if(field==null) {
			return null;
		}
		//3.根据方法名通过反射调用其方法
		Method method=obj.getClass().getMethod(methodName);
		return method.invoke(obj);
	}
	/**
	 * 利用得到的Emp类的对象emp,通过反射获取Emp类的setter方法进行属性设置
	 * @param obj表示Emp类的对象emp
	 * @param myField表示属性名
	 * @param myValue表示属性值
	 */
	public static void setValueObject(Object obj,String myField,String myValue) throws Exception{
		//1.获取反射需要调用的方法名setter
		String methodName="set"+myFirstUpper(myField);
		//2.判断传入的属性名对应的对象是否在obj对应的类中存在,若不存在则直接return
		Field field=obj.getClass().getDeclaredField(myField);
		if(field==null) {
			return;
		}
		//3.根据方法名通过反射调用其方法
		Method setmethod=obj.getClass().getMethod(methodName,field.getType());
		setmethod.invoke(obj,myValue);		
	}
}

运行结果如下所示:

Emp [name=xieguangtao, job=student]

以上就是介绍的关于反射与单级VO操作!











猜你喜欢

转载自blog.csdn.net/tongxuexie/article/details/80410293