background image

所以,除非必要,应尽量避免尽力对象的实例。下面的例子将帮助你理解这条原则:

 

当你从用户输入的数据中截取一段字符串时,尽量使用

substring 函数取得原始数据的一个子串,而不是为子串

另外建立一份拷贝。这样你就有一个新的

String 对象,它与原始数据共享一个 char 数组。

如果你有一个函数返回一个

String 对象,而你确切的知道这个字符串会被附加到一个 StringBuffer,那么,

请改变这个函数的参数和实现方式,直接把结果附加到

StringBuffer 中,而不要再建立一个短命的临时对象。

一个更极端的例子是,把多维数组分成多个一维数组:

 

int 数组比 Integer 数组好,这也概括了一个基本事实,两个平行的 int 数组比(int,int)对象数组性能要好
很多。同理,这试用于所有基本类型的组合。

如果你想用一种容器存储

(Foo,Bar)元组,尝试使用两个单独的 Foo[]数组和 Bar[]数组,一定比(Foo,Bar)

数组效率更高。(也有例外的情况,就是当你建立一个

API,让别人调用它的时候。这时候你要注重对 API 借口

的设计而牺牲一点儿速度。当然在

API 的内部,你仍要尽可能的提高代码的效率)

总体来说,就是避免创建短命的临时对象。减少对象的创建就能减少垃圾收集,进而减少对用户体验的影响。

 

使用本地方法

当你在处理字串的时候,不要吝惜使用

String.indexOf(), String.lastIndexOf()等特殊实现的方法。

这些方法都是使用

C/C++实现的,比起 Java 循环快 10 到 100 倍。

 

但也并非要完全使用本地方法,调用本地方法的代价要高于调用解释方法。所以如果可以避免,就不应使用本地
方法去做一些并不复杂的运算。

 

选择虚类而不是接口

假设你有一个

HashMap 对象,你可以将它声明为 HashMap 或者 Map:

 

Map myMap1 = new HashMap();

HashMap myMap2 = new HashMap();哪个更好呢?

 

按照传统的观点

Map 会更好些,因为这样你可以改变他的具体实现类,只要这个类继承自 Map 接口。传统的观点

对于传统的程序是正确的,但是它并不适合嵌入式系统。调用一个接口的引用会比调用实体类的引用多花费一倍
的时间。

 

如果

HashMap 完全适合你的程序,那么使用 Map 就没有什么价值。如果有些地方你不能确定,先避免使用 Map,

剩下的交给

IDE 提供的重构功能好了。(当然公共 API 是一个例外:一个好的 API 常常会牺牲一些性能)