本文是“
使用反射簡化繁瑣的對對象成員設值取值的過程”的續文。
在前文的例子中,類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.tkk7.com/Files/sitinspring/MemberMethodSetgetValueSample20080105151118.rar