參與大項目的開發(fā)人員通常要花數(shù)個小時編寫有用的 toString 方法。即便不為每個類都提供屬于它們自己的 toString 方法,但每個數(shù)據(jù)容器都必須有自己的 toString 方法。讓每個開發(fā)人員按他們自己的方法編寫 toString 方法可能會造成混亂;每個開發(fā)人員無疑都會提出一種唯一的格式。結果,在調試過程中使用這樣的輸出將增添不必要的麻煩,而且也沒有什么好處。因此,每個項目都應該為 toString 方法規(guī)定一種單一的格式,并使它們的創(chuàng)建自動化。
使 toString 的創(chuàng)建自動化
我下面將演示一個實用程序,您可用它來實現(xiàn) toString 的自動創(chuàng)建。這個工具會自動為指定的類生成一個規(guī)則的、強健的 toString 方法,幾乎消除了用于開發(fā)該方法的時間。它還對 toString() 的格式進行集中治理。假如您更改了格式,則必須重新生成 toString 方法;但是,這仍然比手動更改成百上千個類要輕易得多。
對生成的代碼進行維護也很輕易。假如您在類中添加了更多的屬性,則您也可能需要對 toString 方法作一些修改。因為 toString 方法是自動生成的,所以您只須再次對該類運行這個實用程序來完成更改。這比手動方法更簡單,而且犯錯誤的可能性也較小。
代碼
本文無意解釋 Reflection API;下面的代碼假定您已理解 Reflection 的基本概念。要查看 Reflection API 的文檔,您可以訪問參考資源部分。實用程序的源代碼如下所示:
package fareed.publications.utilities;
import java.lang.reflect.*;
public class ToStringGenerator
{
public static void main(String[] args)
{
if (args.length == 0)
{
System.out. System.exit(0);
}
try {
Class targetClass = Class.forName(args[0]);
if (!targetClass.isPrimitive() && targetClass != String.class)
{
Field fields[] = targetClass.getDeclaredFields();
Class cSuper = targetClass.getSuperclass(); // 檢索超類
output("StringBuffer buffer = new StringBuffer(500);"); // 構造緩沖區(qū)
if (cSuper != null && cSuper != Object.class) {
output("buffer.append(super.toString());"); // 超類的 toString()
}
for (int j = 0; j < fields.length; j++) {
output("buffer.append(/"" + fields[j].getName() + " = /");"); // 附加域名稱
if (fields[j].getType().isPrimitive() fields[j].getType() == String.class) // 檢查基本數(shù)據(jù)類型或字符串類型
output("buffer.append(this." + fields[j].getName() + ");"); // 附加基本數(shù)據(jù)類型域的值
else
{
/* 它“不是”基本數(shù)據(jù)類型域,所以需要檢查聚集對象的 NULL 值 */
output("if ( this." + fields[j].getName() + "!= null )" );
output("buffer.append(this." + fields[j].getName() + ".toString());");
output("else buffer.append(/"value is null/"); ");
} // else 結束
} // 循環(huán)結束
output("return buffer.toString();");
}
} catch (ClassNotFoundException e) {
System.out.println("Class not found in the class path");
System.exit(0);
}
}
private static void output(String data)
{
System.out.println(data);
}
}
代碼輸出通道
代碼的格式還取決于您的項目工具需求。某些開發(fā)人員可能喜歡將這些代碼存入磁盤上用戶定義的文件中。而另一些開發(fā)人員對 system.out 控制臺就很滿足,他們可以利用控制臺手動將這些代碼復制或嵌入實際的文件中。我將這些選擇權留給您,本文只使用最簡單的方法:system.out 語句。
這種方法的局限性
這種方法有兩個明顯的局限性。第一個局限性是它不支持對象的循環(huán)包含。假如對象 A 包含對象 B 的一個引用,對象 B 又包含對象 A 的一個引用,則這個工具無法處理。但是,對于許多項目而言,這種情況很少出現(xiàn)。
第二個局限性是添加或減少成員變量之后要求重新生成 toString 方法。因為不管用不用這個工具都需要完成這一步,所以這不是工具特有的問題。
小結
在本文中,我說明了一個小型的自動實用程序,它可以真正提高開發(fā)人員的效率,就整個項目的工期而言,它起著很小但很重要的作用。
新聞熱點
疑難解答