熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

使toString()的創建自動化

2013-11-15 11:44:11  來源: JSP教程 

  有經驗的 Java 開發人員都知道寫好 toString 方法很重要對可用人類理解的形式查看的對象進行記錄和調試都相當容易當處理分布式應用程序時尤其是這樣不幸的是為許多類實現 toString 方法可能相當耗時 尤其是對於那些具有許多屬性的類因為 toString 的行為相當規則所以最好使創建該方法的任務能夠自動完成本文提供的這個實用程序可以幫助您實現這一點同時也減輕了您在開發時的負擔
  
  參與大項目的開發人員通常要花數個小時編寫有用的 toString 方法即便不為每個類都提供屬於它們自己的 toString 方法但每個數據容器都必須有自己的 toString 方法讓每個開發人員按他們自己的方法編寫 toString 方法可能會造成混亂每個開發人員無疑都會提出一種唯一的格式結果在調試過程中使用這樣的輸出將增添不必要的麻煩而且也沒有什麼好處因此每個項目都應該為 toString 方法規定一種單一的格式並使它們的創建自動化
  
  使 toString 的創建自動化
  我下面將演示一個實用程序您可用它來實現 toString 的自動創建這個工具會自動為指定的類生成一個規則的強健的 toString 方法幾乎消除了用於開發該方法的時間它還對 toString() 的格式進行集中管理如果您更改了格式則必須重新生成 toString 方法但是這仍然比手動更改成百上千個類要容易得多
  
  對生成的代碼進行維護也很容易如果您在類中添加了更多的屬性則您也可能需要對 toString 方法作一些修改因為 toString 方法是自動生成的所以您只須再次對該類運行這個實用程序來完成更改這比手動方法更簡單而且犯錯誤的可能性也較小
  
  代碼
  本文無意解釋 Reflection API下面的代碼假定您已理解 Reflection 的基本概念要查看 Reflection API 的文檔您可以訪問參考資源部分實用程序的源代碼如下所示
  
  package fareedpublicationsutilities;
  import javalangreflect*;
  
  public class ToStringGenerator
  {
  public static void main(String[] args)
  {
  if (argslength == )
  {
  Systemoutprintln(Provide the class name as the command line argument);
  Systemexit();
  }
  
  try {
  
  Class targetClass = ClassforName(args[]);
  
  if (!targetClassisPrimitive() && targetClass != Stringclass)
  {
  Field fields[] = targetClassgetDeclaredFields();
  
  Class cSuper = targetClassgetSuperclass(); // 檢索超類
  
  output(StringBuffer buffer = new StringBuffer();); // 構造緩沖區
  
  if (cSuper != null && cSuper != Object
  
  for (int j = ; j < fieldslength; j++) {
  output(bufferappend(\ + fields[j]getName() + = \);); // 附加域名稱
  
  if (fields[j]getType()isPrimitive() || fields[j]getType() == Stringclass) // 檢查基本數據類型或字符串類型
  output(bufferappend(this + fields[j]getName() + );); // 附加基本數據類型域的值
  else
  {
  /* 它不是基本數據類型域所以需要檢查聚集對象的 NULL 值 */
  output(if ( this + fields[j]getName() + != null ) );
  output(bufferappend(this + fields[j]getName() + toString()););
  output(else bufferappend(\value is null\); );
  } // else 結束
  } // 循環結束
  output(return buffertoString(););
  }
  } catch (ClassNotFoundException e) {
  Systemoutprintln(Class not found in the class path);
  Systemexit();
  }
  }
  
  private static void output(String data)
  {
  Systemoutprintln(data);
  }
  
  }
  
  代碼輸出通道
  代碼的格式還取決於您的項目工具需求某些開發人員可能喜歡將這些代碼存入磁盤上用戶定義的文件中而另一些開發人員對 systemout 控制台就很滿意他們可以利用控制台手動將這些代碼復制或嵌入實際的文件中我將這些選擇權留給您本文只使用最簡單的方法systemout 語句
  
  這種方法的局限性
  這種方法有兩個明顯的局限性第一個局限性是它不支持對象的循環包含如果對象 A 包含對象 B 的一個引用對象 B 又包含對象 A 的一個引用則這個工具無法處理但是對於許多項目而言這種情況很少出現
  
  第二個局限性是添加或減少成員變量之後要求重新生成 toString 方法因為不管用不用這個工具都需要完成這一步所以這不是工具特有的問題
  
  小結
  在本文中我說明了一個小型的自動實用程序它可以真正提高開發人員的效率就整個項目的工期而言它起著很小但很重要的作用
  
  補充技巧
  這篇技巧發表以後我收到讀者關於改進這段代碼的幾點建議在這部分補充內容中我將說明如何根據這些建議以及我自己的見解改進這個實用程序在參考資源部分可找到這些改進的源代碼
  
  改進 在最初的代碼中我沒有處理包含對象和基本數據的數組類型現在新代碼可以處理數組數據但是這段代碼只能處理一維數組而不能處理多維數組我現在還無法提供這個問題的一般解決方案因為就我所知Java 對數據類型的維數沒有限制(只受可用內存的限制)我歡迎您提供解決方案
  
  改進 最初我建議將這個工具用於開發時環境而不是運行時環境允許這個工具在運行時運行很方便但可能會占用更多的 CPU 周期但是對象轉儲/調試(toString() 的基本用途)通常是在開發時進行而在生產環境中要將其關閉在某些情況下如果某些項目可能將 toString() 用於業務邏輯則在生產環境中就可能不能關閉轉儲/調試我建議您根據具體項目決定是否將其關閉
  
  在開發這個實用程序之前我已經想到了這種運行時靈活性首先我開發了一個單獨的授權類客戶端的類用它來生成 toString()這個類利用類似 return ToStringGeneratorgenerateToString(this) 的一個方法調用生成 toString其中 this 指向客戶端類的當前實例這條語句放在 toString() 方法實現中但這個方法失敗了因為 Reflection API 在運行時無法獲取私有成員的值因此這個類只能用於公用成員這不是我所希望的
  
  但後來 Sanscraint 先生指出如果將這段代碼放在同一個調用類的一個方法中則同樣的 Reflection API 代碼就可以獲取私有成員的值因此我修改了這個實用程序以便在運行時使用另外即使在目標類中新增或減少了任何屬性您也不必更新或編輯 toString() 方法
  
  改進 最初我用 this 前綴來訪問生成代碼中的成員變量但 Ye 先生指出這段代碼也可用於靜態方法甚至可用來輸出靜態成員這樣更新後的代碼現在既可處理類成員也可處理實例成員Ye 先生還指出一個錯誤(在此版本中已修正)這個錯誤導致為無屬性的類生成毫無用處的代碼
  
  代碼修改
  在使這個實用程序可用於運行時以後我不得不在每個類中復制/粘貼這些方法因為新代碼由多個方法組成所以這變得很困難我對此感到很沮喪
  
  一種解決方案是創建一個接口/抽象基類這至少解決了方法簽名問題但仍然需要進行復制/粘貼抽象基類還使客戶類無法從另一個類繼承出
  
  但是內部類可以訪問父類的私有成員這樣在內部類的方法中運行的 Reflection 代碼也可以獲取私有值因此我決定將這個實用程序改為內部類它可被插入客戶的任何父類中我還提供了 ToStringGeneratorExamplejava它將 ToStringGeneratorjava 用作內部類來實現 toString() 方法
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19523.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.