国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

使toString()的創(chuàng)建自動(dòng)化

2019-11-18 13:18:50
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  有經(jīng)驗(yàn)的 java 開(kāi)發(fā)人員都知道寫(xiě)好 toString 方法很重要。對(duì)可用人類理解的形式查看的對(duì)象進(jìn)行記錄和調(diào)試都相當(dāng)輕易;當(dāng)處理分布式應(yīng)用程序時(shí)尤其是這樣。不幸的是,為許多類實(shí)現(xiàn) toString 方法可能相當(dāng)耗時(shí) -- 尤其是對(duì)于那些具有許多屬性的類。因?yàn)?toString 的行為相當(dāng)規(guī)則,所以最好使創(chuàng)建該方法的任務(wù)能夠自動(dòng)完成。本文提供的這個(gè)實(shí)用程序可以幫助您實(shí)現(xiàn)這一點(diǎn),同時(shí)也減輕了您在開(kāi)發(fā)時(shí)的負(fù)擔(dān)。
  
  參與大項(xiàng)目的開(kāi)發(fā)人員通常要花數(shù)個(gè)小時(shí)編寫(xiě)有用的 toString 方法。即便不為每個(gè)類都提供屬于它們自己的 toString 方法,但每個(gè)數(shù)據(jù)容器都必須有自己的 toString 方法。讓每個(gè)開(kāi)發(fā)人員按他們自己的方法編寫(xiě) toString 方法可能會(huì)造成混亂;每個(gè)開(kāi)發(fā)人員無(wú)疑都會(huì)提出一種唯一的格式。結(jié)果,在調(diào)試過(guò)程中使用這樣的輸出將增添不必要的麻煩,而且也沒(méi)有什么好處。因此,每個(gè)項(xiàng)目都應(yīng)該為 toString 方法規(guī)定一種單一的格式,并使它們的創(chuàng)建自動(dòng)化。
  
  使 toString 的創(chuàng)建自動(dòng)化
  我下面將演示一個(gè)實(shí)用程序,您可用它來(lái)實(shí)現(xiàn) toString 的自動(dòng)創(chuàng)建。這個(gè)工具會(huì)自動(dòng)為指定的類生成一個(gè)規(guī)則的、強(qiáng)健的 toString 方法,幾乎消除了用于開(kāi)發(fā)該方法的時(shí)間。它還對(duì) toString() 的格式進(jìn)行集中治理。假如您更改了格式,則必須重新生成 toString 方法;但是,這仍然比手動(dòng)更改成百上千個(gè)類要輕易得多。
  
  對(duì)生成的代碼進(jìn)行維護(hù)也很輕易。假如您在類中添加了更多的屬性,則您也可能需要對(duì) toString 方法作一些修改。因?yàn)?toString 方法是自動(dòng)生成的,所以您只須再次對(duì)該類運(yùn)行這個(gè)實(shí)用程序來(lái)完成更改。這比手動(dòng)方法更簡(jiǎn)單,而且犯錯(cuò)誤的可能性也較小。
  
  代碼
  本文無(wú)意解釋 Reflection API;下面的代碼假定您已理解 Reflection 的基本概念。要查看 Reflection API 的文檔,您可以訪問(wèn)參考資源部分。實(shí)用程序的源代碼如下所示:
  
  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);"); // 構(gòu)造緩沖區(qū)
  
  if (cSuper != null && cSuper != Object
  
  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ù)類型域,所以需要檢查聚集對(duì)象的 NULL 值 */
  output("if ( this." + fields[j].getName() + "!= null )" );
  output("buffer.append(this." + fields[j].getName() + ".toString());");
  output("else buffer.append(/"value is null/"); ");
  } // else 結(jié)束
  } // 循環(huán)結(jié)束
  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);
  }
  
  }
  
  代碼輸出通道
  代碼的格式還取決于您的項(xiàng)目工具需求。某些開(kāi)發(fā)人員可能喜歡將這些代碼存入磁盤(pán)上用戶定義的文件中。而另一些開(kāi)發(fā)人員對(duì) system.out 控制臺(tái)就很滿足,他們可以利用控制臺(tái)手動(dòng)將這些代碼復(fù)制或嵌入實(shí)際的文件中。我將這些選擇權(quán)留給您,本文只使用最簡(jiǎn)單的方法:system.out 語(yǔ)句。
  
  這種方法的局限性
  這種方法有兩個(gè)明顯的局限性。第一個(gè)局限性是它不支持對(duì)象的循環(huán)包含。假如對(duì)象 A 包含對(duì)象 B 的一個(gè)引用,對(duì)象 B 又包含對(duì)象 A 的一個(gè)引用,則這個(gè)工具無(wú)法處理。但是,對(duì)于許多項(xiàng)目而言,這種情況很少出現(xiàn)。
  
  第二個(gè)局限性是添加或減少成員變量之后要求重新生成 toString 方法。因?yàn)椴还苡貌挥眠@個(gè)工具都需要完成這一步,所以這不是工具特有的問(wèn)題。
  
  小結(jié)
  在本文中,我說(shuō)明了一個(gè)小型的自動(dòng)實(shí)用程序,它可以真正提高開(kāi)發(fā)人員的效率,就整個(gè)項(xiàng)目的工期而言,它起著很小但很重要的作用。
  
  補(bǔ)充技巧
  這篇技巧發(fā)表以后,我收到讀者關(guān)于改進(jìn)這段代碼的幾點(diǎn)建議。在這部分補(bǔ)充內(nèi)容中,我將說(shuō)明如何根據(jù)這些建議以及我自己的見(jiàn)解改進(jìn)這個(gè)實(shí)用程序。在參考資源部分可找到這些改進(jìn)的源代碼。
  
  改進(jìn) 在最初的代碼中,我沒(méi)有處理包含對(duì)象和基本數(shù)據(jù)的數(shù)組類型;現(xiàn)在新代碼可以處理數(shù)組數(shù)據(jù)。但是,這段代碼只能處理一維數(shù)組,而不能處理多維數(shù)組。我現(xiàn)在還無(wú)法提供這個(gè)問(wèn)題的一般解決方案,因?yàn)榫臀宜琂ava 對(duì)數(shù)據(jù)類型的維數(shù)沒(méi)有限制(只受可用內(nèi)存的限制)。我歡迎您提供解決方案。
  
  改進(jìn) 最初我建議將這個(gè)工具用于開(kāi)發(fā)時(shí)環(huán)境,而不是運(yùn)行時(shí)環(huán)境。答應(yīng)這個(gè)工具在運(yùn)行時(shí)運(yùn)行很方便,但可能會(huì)占用更多的 CPU 周期。但是,對(duì)象轉(zhuǎn)儲(chǔ)/調(diào)試(toString() 的基本用途)通常是在開(kāi)發(fā)時(shí)進(jìn)行,而在生產(chǎn)環(huán)境中要將其關(guān)閉。在某些情況下,假如某些項(xiàng)目可能將 toString() 用于業(yè)務(wù)邏輯,則在生產(chǎn)環(huán)境中就可能不能關(guān)閉轉(zhuǎn)儲(chǔ)/調(diào)試。我建議您根據(jù)具體項(xiàng)目決定是否將其關(guān)閉。
  
  在開(kāi)發(fā)這個(gè)實(shí)用程序之前,我已經(jīng)想到了這種運(yùn)行時(shí)靈活性。首先,我開(kāi)發(fā)了一個(gè)單獨(dú)的授權(quán)類,客戶端的類用它來(lái)生成 toString()。這個(gè)類利用類似 return ToStringGenerator.generateToString(this) 的一個(gè)方法調(diào)用生成 toString,其中 this 指向客戶端類的當(dāng)前實(shí)例,這條語(yǔ)句放在 toString() 方法實(shí)現(xiàn)中。但這個(gè)方法失敗了,因?yàn)?Reflection API 在運(yùn)行時(shí)無(wú)法獲取私有成員的值。因此這個(gè)類只能用于公用成員,這不是我所希望的。
  
  但后來(lái) Sanscraint 先生指出,假如將這段代碼放在同一個(gè)調(diào)用類的一個(gè)方法中,則同樣的 Reflection API 代碼就可以獲取私有成員的值。因此,我修改了這個(gè)實(shí)用程序以便在運(yùn)行時(shí)使用,另外,即使在目標(biāo)類中新增或減少了任何屬性,您也不必更新或編輯 toString() 方法。
  
  改進(jìn) 最初我用 this 前綴來(lái)訪問(wèn)生成代碼中的成員變量,但 Ye 先生指出,這段代碼也可用于靜態(tài)方法,甚至可用來(lái)輸出靜態(tài)成員。這樣,更新后的代碼現(xiàn)在既可處理類成員,也可處理實(shí)例成員。Ye 先生還指出一個(gè)錯(cuò)誤(在此版本中已修正),這個(gè)錯(cuò)誤導(dǎo)致為無(wú)屬性的類生成毫無(wú)用處的代碼。
  
  代碼修改
  在使這個(gè)實(shí)用程序可用于運(yùn)行時(shí)以后,我不得不在每個(gè)類中復(fù)制/粘貼這些方法,因?yàn)樾麓a由多個(gè)方法組成,所以這變得很困難,我對(duì)此感到很沮喪。
  
  一種解決方案是創(chuàng)建一個(gè)接口/抽象基類,這至少解決了方法簽名問(wèn)題,但仍然需要進(jìn)行復(fù)制/粘貼。抽象基類還使客戶類無(wú)法從另一個(gè)類繼續(xù)出。
  
  但是,內(nèi)部類可以訪問(wèn)父類的私有成員,這樣在內(nèi)部類的方法中運(yùn)行的 Reflection 代碼也可以獲取私有值。因此我決定將這個(gè)實(shí)用程序改為內(nèi)部類,它可被插入客戶的任何父類中。我還提供了 ToStringGeneratorExample.java,它將 ToStringGenerator.java 用作內(nèi)部類來(lái)實(shí)現(xiàn) toString() 方法。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 达日县| 通河县| 措美县| 尉犁县| 拜城县| 平利县| 定边县| 伊宁县| 大连市| 绵阳市| 蒙自县| 甘德县| 米易县| 临湘市| 岑溪市| 佛冈县| 马关县| 顺平县| 阿克陶县| 本溪市| 沙田区| 炉霍县| 贵港市| 交口县| 石棉县| 安新县| 固阳县| 运城市| 绥德县| 昭苏县| 米泉市| 通榆县| 福鼎市| 大新县| 康乐县| 和平县| 富阳市| 晋宁县| 庆阳市| 马边| 应用必备|