在讲关于反射与单级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操作!