实例大型企业门户网站页架构生成源代码优化 在 RegExpMatcher 的例子中, 你看见了 当一个方法返回一个 String 类型时, 它通常需要新建一个 String 对象. BadRegExpMatcher 的一个问题就是 match() 返回一个对象而不是一个原类型 -- 但是只因为一个方法返回一个对象, 不意味着必须有一个新对象创建. 考虑一下 java.awt 中的几何类, 象 Point 和 Rectangle. 一个 Rectangle只是四个整数(x, y, 宽度, 长度)的容器, AWT Component 类存储组件的位置, 通过getBounds()作为一个Rectangle 返回 public class Component { ... public Rectangle getBounds(); } 在上面的例子中, getBounds() 只是一个存储元 -- 它只使一些 Component 内部的一些状态信息可用. 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 是可变的, 它在 Component 不知道的情况下使 Component 移动. 对象AWT 这样的 GUI 工具箱来说, 这是个灾难, 因为当一个组件移动以后, 屏幕需要重绘, 组件**需要被通知, 等等. 所以上面的实现 Component.getBounds() 的代码看起来很危险. 一个安全一点的实现就象下面这样: public Rectangle getBounds() { return new Rectangle(myBounds.x, myBounds.y, myBounds.height, myBounds.width); } 但是现在, 每一个 getBounds() 的调用都创建一个新对象, 就象 RegExpMatcher 一样.实际上, 下面的代码片段创建了 4 个临时对象: 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 的情况下很好, 这个方法不总是可行的或者是希望的. 幸运的是, 你可以在实际类的时候可以使用一些技巧, 来免除太多小对象的问题, 而不是完全避免小对象. 减少对象的技巧 1: 加上好的存取函数 在 Swing 工具箱的初始版本中, 小对象的临时创建, 象 Point, Rectangle 和 Dimension极大地阻碍了性能. 把它们放在一个 Point 或者 Rectangle 中来一次返回多个值, 看起来更有效, 实际上, 对象的创建比多个方法调用代价更高. 在 Swing 的最后发布之前, 通过给 Component 和其他一些类加一些新的存取方法, 问题就简单地解决了, 就象下面这样: public int getX() { return myBounds.x; } public int getY() { return myBounds.y; } public int getHeight() { return myBounds.height
|
|
|
|
|