因为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类似的场合中,这一方案并非总是可行的或理想的,然而,幸运的是,在设计类时可以采用一些技术,既能使用小一些的对象又不会遇到使用太多的小对象所引起的问题。
数据类型对软件性能的影响
BadRegExpMatcher要求MailBot将输入文本由字符数组转换为一个String对象,从而导致了不必要的对象创建。然而,滑稽的是为了更方便地使用输入文本,BadRegExpMatcher会立即将String对象转换为一个字符数组,这样不但会生成另一个对象,还意味着你在费了九牛二虎之力得到的结果,跟调用程序最初提供的数据没有什么二样,MailBot和BadRegExpMatcher都不要求使用String对象,String对象似乎仅仅是为也在组件之间交换文本数据而存在的。
在上面的BadRegExpMatcher例子中,String仅仅是一种供交换用的类型,无论是调用程序还是被调用程序都不需要使用供交换用的数据类型来表示数据,但它们可以很方便地把它与其他的数据类型进行转换。尽管在定义接口时采用供交换用的数据类型可以在保持灵活性的前提下降低复杂性,但有时会带来性能上的损失。
供交换用数据类型的一个最常见的例子是JDBC ResultSet接口,没有一种数据库的接口会用JDBC ResultSet表示返回的结果,但JDBC驱动程序可以很方便地把数据库返回的结果转换为JDBC ResultSet型数据。同样,也没有一种客户端软件用DBC ResultSet型数据表示数据记录,但你也可以不费什么劲儿就将ResultSet型数据转换为所需要的数据类型。在JDBC中我们可以接受这种"多此一举",因为它具有标准性和跨数据库的可移植性等好处。无论如何,由供交换用数据类型所带来的性能损失都是一个值得注意的问题。
文章来源于领测软件测试网 https://www.ltesting.net/