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

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

為JAVA性能而設計(2)

2019-11-18 12:23:11
字體:
來源:轉載
供稿:網友

  作者:eclipse
  
  為性能而設計, 第二部分: 減少對象創建[/b]
  
  From java World.
  
  [b]在設計 Java 類的時候避免性能上的冒險[/b]
  
  [b][u]概要[/u][/b]
  
  許多通常的 Java 性能問題都起源于在設計過程早期中的類設計的思想, 早在許多開發者
  開始考慮性能問題之前. 在這個系列中, Brian Goetz 討論了通常的 Java 性能上的冒險
  以及怎么在設計時候避免它們. 在第二部分, 他討論了減少臨時對象創建的一些技術.
  (1,700 字)
  
  By Brian Goetz
  
  翻譯 by SuperMMX
  
  閱讀整個"為性能而設計"系列:
  
  第一部分: 接口事宜
  第二部分: 減少對象創建
  第三部分: 遠程接口 (March 23, 2001)
  
  雖然許多程序員把性能治理一直推遲到開發過程的最后, 性能考慮應該從第一天起就和設
  計周期結合在一起. 這個系列探索一些早期的設計思想能夠極大影響應用程序性能的方法.
  在這篇文章里, 我繼續探索大量臨時對象創建的問題, 并且提供一些避免它們的一些技術.
  
  臨時對象就是一些生命周期比較短的對象, 一般用于保存其他數據而再沒有其他用途. 程
  序員一般用臨時變量向一個方法傳遞數據或者從一個方法返回數據. 第一部分探討了臨時
  對象是怎樣給一個程序的性能帶來負面的沖擊, 以及一些類接口的設計思想怎樣提供了臨
  時對象的創建. 避免了那些接口的創建, 你就能極大地減少那些影響你的程序性能的臨時
  對象創建的需求,
  
  [b][u]只是對 String 說不嗎?[/u][/b]
  
  當它要創建臨時變量時, String 類是最大的罪人中的一個. 為了演示, 在第一部分我寫了
  一個正規表達式匹配的例子, 通過和一個類似的但是經過仔細設計的接口相比較, 演示了
  看起來無害的接口是怎樣引起大量對象的創建, 而慢上幾倍. 這里是原來的和好一些的類
  的接口:
  
  BadRegEXPMatcher
  
  [code]
  public class BadRegExpMatcher {
   public BadRegExpMatcher(String regExp);
   /** Attempts to match the specified regular exPRession against the input
   text, returning the matched text if possible or null if not */
   public String match(String inputText);
  }
  [/code]
  
  BetterRegExpMatcher
  
  [code]
  class BetterRegExpMatcher {
   public BetterRegExpMatcher(...);
   /** Provide matchers for multiple formats of input -- String,
   character array, and subset of character array. Return -1 if no
   match was made; return offset of match start if a match was
   made. */
   public int match(String inputText);
   public int match(char[] inputText);
   public int match(char[] inputText, int offset, int length);
   /** If a match was made, returns the length of the match; between
   the offset and the length, the caller should be able to
   reconstrUCt the match text from the offset and length */
   public int getMatchLength();
   /** Convenience routine to get the match string, in the event the
   caller happens to wants a String */
   public String getMatchText();
  }
  [/code]
  
  大量使用 BadREgExpMatcher 的程序比使用 BTterRegExpMatcher 的要慢好多. 首先,
  調用者不得不創建一個 String 傳入 match(), 接著 match() 又創建了一個 String 來
  返回匹配的文本. 結果是每次調用都有兩個對象創建, 看起來不多, 但是假如要經常調用
  match(), 這些對象創建帶給性能的代價就太打了. BadRegExpMatcher 的性能問題不是在
  它的實現中, 而是它的接口; 象它定義的接口, 沒有辦法避免一些臨時變量的創建.
  
  BetterRegExpMatcher 的 match() 用原類型(整數和字符數組)代替了 String 對象; 不需
  要創建中間對象來在調用者和 match() 之間傳遞信息.
  
  既然在設計時候避免性能問題要比寫完整個系統以后再修改要輕易一些, 你應該注重你的
  類中控制對象創建的方法. 在 RegExpMatcher 的例子中, 它的方法要求和返回 String
  對象, 就應該為潛在的性能冒險提個警告信號. 因為 String 類是不可變的, 除了最常用
  以外, 所有的 String 參數在每次調用處理函數時都需要創建一個新的 String.
  
  [b][u]不可變性對于性能來說是否很壞?[/u][/b]
  
  因為 String 經常和大量的對象創建聯系在一起, 一般來說歸咎于它的不可變性. 許多
  程序員認為不可變的對象與生俱來對性能沒有好處. 但是, 事實多少會更復雜一些. 實
  際上, 不可變性有時候提供了性能上的優勢, 可變性的對象有時候導致性能問題. 不管可
  變性對性能來說有幫助或者有害, 依靠于對象是怎么使用的.
  
  程序經常處理和修改文本字符串 -- 和不可變性非常不匹配. 每次你想處理一個 String --
  想查找和解析出前綴或者子串, 變小寫或者大寫, 或者把兩個字符串合并 -- 你必須創建
  一個新的 String 對象. (在合并的情況下, 編譯器也會隱藏地創建一個 StringBuffer()
  對象)
  
  另一個方面, 一個不可變的對象的一個引用可以自由共享, 而不用擔心被引用的對象要被
  修改, 這個比可變對象提供性能優勢, 就象下一節例子所說的.
  
  [b][u]可變的對象有它們自己的臨時對象問題. [/u][/b]
  
  在 RegExpMatcher 的例子中, 你看見了 當一個方法返回一個 String 類型時, 它通常
  需要新建一個 String 對象. BadRegExpMatcher 的一個問題就是 match() 返回一個對
  象而不是一個原類型 -- 但是只因為一個方法返回一個對象, 不意味著必須有一個新對
  象創建. 考慮一下 java.awt 中的幾何類, 象 Point 和 Rectangle. 一個 Rectangle
  只是四個整數(x, y, 寬度, 長度)的容器. AWT Component 類存儲組件的位置, 通過
  getBounds()作為一個Rectangle 返回
  
  [code]
  public class Component {
   ...
   public Rectangle getBounds();
  }
  [/code]
  
  在上面的例子中, getBounds() 只是一個存儲元 -- 它只使一些 Component 內部的一
  些狀態信息可用. getBounds() 需要創建它返回的 Rectangle 嗎? 可能. 考慮一下下面
  getBounds() 可能的實現.
  
  [code]
  public class Component {
   ...
   protected Rectangle myBounds;
   public Rectangle getBounds() { return myBounds; }
  }
  [/code]
  
  當一個調用者調用上面例子中的 getBounds(), 沒有新對象創建 -- 因為組件已經知道它
  在哪里 -- 所以 getBounds() 效率很高. 但是 Rectangle 的可變性又有了其他問題. 當
  一個調用者運行一下程序會發生什么呢?
  
  [code]
   Rectangle r = component.getBounds();
   ...
   r.height *= 2;
  [/code]
  
  因為 Rectangle 是可變的, 它在 Component 不知道的情況下使 Component 移動. 對象
  AWT 這樣的 GUI 工具箱來說, 這是個災難, 因為當一個組件移動以后, 屏幕需要重繪,
  件監聽器需要被通知, 等等. 所以上面的實現 Component.getBounds() 的代碼看起來很
  危險. 一個安全一點的實現就象下面這樣:
  
  [code]
   public Rectangle getBounds() {
   return new Rectangle(myBounds.x, myBounds.y,
   myBounds.height, myBounds.width);
   }
  [/code]
  
  但是現在, 每一個 getBounds() 的調用都創建一個新對象, 就象 RegExpMatcher 一樣.
  實際上, 下面的代碼片段創建了 4 個臨時對象:
  
  [code]
   int x = component.getBounds().x;
   int y = component.getBounds().y;
   int h = component.getBounds().height;
   int w = component.getBounds().width;
  [/code]
  
  在 String 的情況中, 對象創建是必要的, 因為 String 是不可變的. 但在這個例子中,
  對象的創建也是必要的, 因為 Rectangle 是可變的. 我們使用 String 避免了這個問題,
  在我們的接口中沒有使用對象. 雖然在 RegExpMatcher 的情況下很好, 這個方法不總是
  可行的或者是希望的. 幸運的是, 你可以在實際類的時候可以使用一些技巧, 來免除太多
  小對象的問題, 而不是完全避免小對象.
  
  [b][u]減少對象的技巧 1: 加上好的存取函數[/u][/b]
  
  在 Swing 工具箱的初始版本中, 對象小對象的臨時創建, 象 Point, Rectangle 和 Dimension
  極大地阻礙了性能. 把它們放在一個 Point 或者 Rectangle 中來一次返回多個值, 看起
  來更有效, 實際上, 對象的創建比多個方法調用代價更高. 在 Swing 的最后發布之前, 通
  過給 Component 和其他一些類加一些新的存取方法, 問題就簡單地解決了, 就象下面這樣:
  
  [code]
   public int getX() { return myBounds.x; }
   public int getY() { return myBounds.y; }
   public int getHeight() {

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 嵊泗县| 邹平县| 合肥市| 双桥区| 定安县| 依安县| 彰化县| 丘北县| 突泉县| 江西省| 大新县| 泸溪县| 运城市| 峡江县| 温宿县| 彩票| 搜索| 汤阴县| 江孜县| 乐平市| 华容县| 大城县| 资溪县| 贵阳市| 黄骅市| 青田县| 克山县| 金平| 安泽县| 婺源县| 江阴市| 南汇区| 台东市| 德阳市| 全州县| 古交市| 洮南市| 上饶县| 洪洞县| 隆尧县| 镇江市|