本文是“
使用反射简化繁琐的对对象成员设值取值的过程”的续文。
在前文的例子中,类MemberInfo的成员变量都是String类型,如果说其中有其它类型int,boolean等,如果变成下面的类:
public class Member{
private String name;
private String title;
private int age;
private boolean isMale;
}
这样以前的给字段设置值的方法就不好用了,如之奈何?
其实只要肯想,办法是有的,反射的getField不好用了,我们还有getMethod,胡屠户死了,咱们也不吃带毛的猪。通过反射的getMethod方法,咱们可以得到类中定义的函数,再对类的getter、setter函数动动手脚就能达到我们的目的。
请看代码,特别是带注释的动了手脚的函数部分。
新定义的Member类:
package com.sitinspring;
public class Member{
private String name;
private String title;
private int age;
private boolean isMale;
public Member(){
}
public Member(String name,String title,int age,boolean isMale){
this.name=name;
this.title=title;
this.age=age;
this.isMale=isMale;
}
/** *//**
* 额外增加的从整数类型年龄得到为字符状态年龄的函数
* @return
*/
public String getAge() {
return String.valueOf(age);
}
/** *//**
* 额外增加的将字符状态年龄转化为整数类型年龄的函数
* @param age
*/
public void setAge(String age) {
this.age = Integer.valueOf(age);
}
/** *//**
* 额外增加的取得字符类型性别的函数
* @return
*/
public String getIsMale() {
return isMale?"男":"女";
}
/** *//**
* 额外增加的将字符类型性别转化为布尔类型性别的函数
* @param strMale
*/
public void setIsMale(String strMale) {
this.isMale = strMale.equals("男");
}
/** *//**
* 改写的函数,将生成的getAge变成了getIntAge
* @return
*/
public int getIntAge() {
return age;
}
public String toString(){
return "Name="+name+" Title="+title+" Age="+age+" 性别="+getIsMale();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setAge(int age) {
this.age = age;
}
public boolean isMale() {
return isMale;
}
public void setMale(boolean isMale) {
this.isMale = isMale;
}
}
上面四个函数就是为了方便反射而写的,再看MemberPersistence的代码:
package com.sitinspring;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/** *//**
* 用于将Member类实例存到XML文件及从XML文件中取出
*
* @author: sitinspring(junglesong@gmail.com)
* @date: 2008-1-3
*/
public class MemberPersistence {
// XML 文件名
private final String xmlFile;
// XML 文档对象
private Document document;
// XML 文档根节点
private Element root;
/** *//**
* 构造函数,其中实例化文档对象和根节点
*
* @param xmlFile
*/
public MemberPersistence(String xmlFile) {
this.xmlFile = xmlFile;
File file = new File(xmlFile);
try {
// 判断文件的存在以增强程序的健壮性
if (file.exists()) {
// 文件存在,直接从文件读取文档对象
SAXReader reader = new SAXReader();
document = reader.read(file);
root = document.getRootElement();
} else {
// 文件不存在,创建文档对象
document = DocumentHelper.createDocument();
root = document.addElement("companies");// 创建根节点
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
/** *//**
* 从XML文件中提取所有Member节点的信息,作为链表返回
*
* @return
*/
public List<Member> loadFromXml() {
List<Member> retval = new ArrayList<Member>();
try {
List nodes = root.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element memberElm = (Element) it.next();
Member member = new Member();
// 取得MemberInfo类的所有定义的成员变量,注意DeclaredFields不包括继承下来的成员变量
Field[] fields = member.getClass().getDeclaredFields();
// 设置每个成员变量的值
for (Field field : fields) {
String fieldText = memberElm.elementText(field.getName());
// 通过反射取得setter函数(通过getSetMethodName函数得出,参数为成员名),其参数为String
Method method = member.getClass().getMethod(
getSetMethodName(field.getName()),
new Class[] { String.class });
// 通过反射调用setter函数给成员变量赋值
method.invoke(member, new Object[] { fieldText });
}
retval.add(member);
}
return retval;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/** *//**
* 将一个Member对象写到XML文件中
*
* @param member
*/
public void writeToXml(Member member) {
try {
// 在根节点下增加一个member节点
Element memberElm = root.addElement("member");
// 取得MemberInfo类的所有定义的成员变量,注意DeclaredFields不包括继承下来的成员变量
Field[] fields = member.getClass().getDeclaredFields();
// 取得每个成员变量的值
for (Field field : fields) {
// 在member节点下添加属性节点
Element fieldElm = memberElm.addElement(field.getName());
// 通过反射取得getter函数(通过getGetMethodName函数得出,参数为成员名),其参数无
Method method = member.getClass().getMethod(
getGetMethodName(field.getName()), new Class[] {});
// 通过反射调用getter函数给取得成员变量的值
Object result = method.invoke(member, new Object[] {});
// 将此值赋给节点文字
fieldElm.setText((String) result);
}
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("GBK"); // 指定XML编码
XMLWriter writer = new XMLWriter(new FileWriter(xmlFile), format);
writer.write(document);
writer.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
/** *//**
* 取得“getter”函數的函數名
*
* @param field
* @return
*/
private static String getGetMethodName(String field) {
return "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
}
/** *//**
* 取得“setter”函數的函數名
*
* @param field
* @return
*/
private static String getSetMethodName(String field) {
return "set" + field.substring(0, 1).toUpperCase() + field.substring(1);
}
}
最后的调用处还是和上篇差不多:
package com.sitinspring;
import java.util.List;
public class Main{
public static void main(String[] args){
MemberPersistence persistence=new MemberPersistence("member.xml");
// 1.写入过程
Member andy=new Member("Andy","SSE",25,true);
Member bill=new Member("Bill","PM",26,false);
persistence.writeToXml(andy);
persistence.writeToXml(bill);
// 2.读出过程
List<Member> members=persistence.loadFromXml();
for(Member member:members){
System.out.println(member);
}
}
}
生成的文件:
<?xml version="1.0" encoding="GBK"?>
<companies>
<member>
<name>Andy</name>
<title>SSE</title>
<age>25</age>
<isMale>男</isMale>
</member>
<member>
<name>Bill</name>
<title>PM</title>
<age>26</age>
<isMale>女</isMale>
</member>
</companies>
代码下载(请自行加入dom4j包):
http://www.blogjava.net/Files/sitinspring/MemberMethodSetgetValueSample20080105151118.rar