可變對象也存在臨時對象問題
![]()
在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類似的場合中,這一方案并非總是可行的或理想的,然而,幸運的是,在設計類時可以采用一些技術,既能使用小一些的對象又不會碰到使用太多的小對象所引起的問題。
進入討論組討論。