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

首頁 > 學院 > 開發設計 > 正文

臨時對象對軟件性能的影響

2019-11-17 04:40:57
字體:
來源:轉載
供稿:網友

   臨時對象的存在時間一般都比較短暫,除了作為其他數據的容器外,沒有其他什么用途,開發人員一般用它向方法傳遞數據或從方法中返回數據。文章的第一部分探討了創建臨時對象是如何影響程序性能的,并表明恰當的類的接口設計可以有效地減少臨時對象的創建。
通過避免設計這樣的接口,就可以減少臨時對象的創建,降低對程序性能的影響程度。在本篇文章中,我將討論過多地創建臨時對象的問題并在后面的文章中提供一些成熟的技術來避免過多地創建臨時對象。

  僅僅對String說NO?

  說到創建臨時對象,String類是最大的"罪魁禍手"。為了說明這一點,我在這篇文章的第一部分中開發了一個表達式匹配類的例子,并演示了一個看起來頗為正常的接口是如何因為創建了臨時對象而比一個具有較好接口的類似的類運行速度慢數倍的。下面是最初的和性能較好的類的接口:

  BadRegEXPMatcher

  public class BadRegExpMatcher {

   public BadRegExpMatcher(String regExp);

   /** 把輸入文本與特定的表達式進行匹配,假如匹配則返回匹配的文本,否則返回空字符 */

   public String match(String inputText);

  }

  BetterRegExpMatcher

  class BetterRegExpMatcher {

   public BetterRegExpMatcher(...);

   /** 向匹配子程序提供多種格式的輸入━━String、字符數組和字符數組的子集。假如不匹配則返回-1,假如匹配,則返回匹配開始處的偏移量 */

   public int match(String inputText);

   public int match(char[] inputText);


   public int match(char[] inputText, int offset, int length);

   /** 假如匹配,則返回匹配的長度,調用程序可以從返回的匹配開始處偏移量和長度重新構造匹配的文本 */

   public int getMatchLength();

   /** 假如調用程序需要,這個例程可以很方便地構造出匹配字符串 */

   public String getMatchText();

  }

  大量使用BadRegExpMatcher的程序要比使用BetterRegExpMatcher的程序運行速度慢一些。第一,調用程序必須創建String對象向match()傳遞參數,match()也必須創建一個String對象向調用程序返回匹配的文本。每次調用時都會創建二個對象,這聽起來也許沒有什么大問題,但假如頻繁地調用match(),創建這二個對象對性能產生的影響就大了。使用BadRegExpMatcher的程序的性能問題并不源于其編碼而源于其接口,象這樣設計的接口,臨時對象的創建是不可避免的。

  BetterRegExpMatcher用比較簡單的數據類型(整型、字符數組)取代了在match()中使用的String對象,從而無需在調用程序和match()之間通過中間對象傳遞數據。

  由于在設計階段比在完成整個程序后再進行修改能夠更好地避免程序性能方面的問題,因此應該在類的接口如何處理對象的創建這個問題上多花些時間。在RegExpMatcher中,其方法要求輸入和返回String對象就可能對性能有潛在的影響,因為String類的對象是不可變的,因此對String類對象參數進行處理就會要求在每次調用時創建一個新的String對象。

  由于不可變性通常與額外的對象創建聯系在一起━━這大部分原因都要"歸功"于其不可變性,許多編程人員就斷定不可變的對象一定會影響程序的性能。其實真實的情況要復雜得多,實際上,不可變性有時還能夠提升程序的性能,可變的對象也能夠引起程序性能的下降,可變性對程序性能的影響取決于其使用方式。

  程序會經常對文本字符串進行操作和修改━━不可改變性確實是一個麻煩。在每次對String進行操作時━━例如查找或選擇一個前綴或子串,把它轉換為大寫或小寫,或者將二個字符串合并成一個新的字符串時,就必須創建一個新的String類對象。

  另一方面,我們可以自由地共享一個不可變對象的地址而無需擔心對象會被改變,此時,不可變對象在性能上就比可變對象要好許多。進入討論組討論。

  可變對象也存在臨時對象問題


  在RegExpMatcher中,當一個方法返回的數據類型為String類時,就有必要創建一個新的String類對象。在BadRegExpMatcher中存在的問題之一是match()返回的是一個對象而不是一個簡單類型的數據━━因為一個方法返回一個對象,并不意味著一定會創建一個新的對象。考慮一下Point和Rectangle等java.awt中的幾何類,一個Rectangle只不過是由四個整數━━左上角點的X、Y坐標以及寬度和高度組成的,AWT組件類存儲了組件的位置并通過getBounds()方法將它作為一個Rectangle類對象返回:

  public class Component {
   ...
  public Rectangle getBounds();
  }

  在上面的例子中,getBounds()方法僅僅起一個輔助性作用,它只是聲明一些組件內部的有關信息。getBounds()真的必須創建它返回的Rectangle對象嗎?也許是這樣的吧,我們來看一下getBounds()的編碼:

  public class Component {
   ...
  PRotected Rectangle myBounds;

  public Rectangle getBounds() { return myBounds; }
  }

  當有程序調用上面例子中的getBounds()時,并不會創建新的對象,因為組件已經知道它的位置,因此getBounds()是比較高效的。然而,Rectangle的可變性還引起了其他問題,當一個調用它的程序執行下面的代碼時會出現什么樣的情況呢?

  Rectangle r = component.getBounds();
   ...
   r.height *= 2;

  因為Rectangle具有可變性,上面的代碼將引起組件的改變,對于象AWT這樣的GUI工具包而言,這將是災難性的,因為當一個組件變化時,需要重新刷新屏幕,同時還需要通知事件監視程序。因此上面的Component.getBounds()的運行是相當危險的,下面所示的方式才是比較安全的:

  public Rectangle getBounds() {
   return new Rectangle(myBounds.x, myBounds.y,
   myBounds.height, myBounds.width);
  }

  但是,就象RegExpMatcher那樣,每次調用getBounds()都會創建一個新的對象,下面的代碼將會創建四個臨時對象:

  int x = component.getBounds().x;
  int y = component.getBounds().y;
  int h = component.getBounds().height;
  int w = component.getBounds().width;

  對于String類而言,創建對象是必要的,因為String是不可變的。但是在這個例子中,創建臨時對象似乎也是必需的,因為Rectangle具有可變性,我們可以通過不在接口中使用任何對象來避免象String引起的那樣的問題。盡管在與RegExpMatcher類似的場合中,這一方案并非總是可行的或理想的,然而,幸運的是,在設計類時可以采用一些技術,既能使用小一些的對象又不會碰到使用太多的小對象所引起的問題。

   進入討論組討論。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 鹤峰县| 广汉市| 蒙自县| 漳州市| 河东区| 娄烦县| 文成县| 兰州市| 汶川县| 辽阳市| 博爱县| 南陵县| 离岛区| 湛江市| 富锦市| 大安市| 金沙县| 遵化市| 韶山市| 新密市| 兴文县| 津南区| 石河子市| 辰溪县| 曲松县| 壶关县| 苏尼特左旗| 阿勒泰市| 沾益县| 屏东县| 炉霍县| 武义县| 义乌市| 东莞市| 桦南县| 溆浦县| 尉氏县| 东源县| 安化县| 平远县| 延津县|