1. 性能优化
a) 如欲进行字符吕接合,stringbuffer 优于string
b) 将对象的创建成本(cre ation cost)降至最小
在对象构建过程中,为确保其正确性,以下事件一定会以固定顺序放生:
i> 从heap 之中分配内存,用以存放全部的instance 变量以及这个对象连同其superclasses 的实现专届数据(implementation-specific data)。所谓[实现专属数据]包括指向“class and method data”的指针。
ii> 对象的instance 变量被初始化为其相应的缺省值。
iii> 调用most derived class(最深层派生类)的构造函数(constructor)。构造函数做的第一件事就是调用superclass 的构造函数。这个程序一直反复持续到java.1ang.object 构造函数被调用为止。一定要记住,java.1ang.object 是一切Java 对象的base class。
iiii> 在构造函数本体执行之前,所有instance 变量的初始值设定式(initializers) 和初始化区段(initialization blocks)先获得执行,然后才执行构造函数本体。于是base class 的构造函数最先执行,most derived class 的构造函数最后执行。这使得任何class 的构造函数都能放心大胆地使用其任何superclasses 的instance 变量。
创建对象过程:
class Light{
private int val;
private boolean hasData = true;
public Light(int a){
val = a;
}
}
Light light = new Light(5);
Light对象建立步骤如下:
I> 从heap分配内存,用来存放Light累的实例变量,以及一份[实现专属数据]
II> 此class的instance变量val和hasData,被初始化为相应的缺省值,val = 0; hasData = false;
III> 调用Light构造函数,传入值为5
IV> 调用Light构造函数调用其父类(本例为java.lang.Object)的构造函数
V > 一旦java.lang.object构造函数返回,Light构造函数执行其实例的初始设定工作,将hasData赋值为true;
VI > 将val赋值为5,而后Light构造函数结束
VII > 对象的引用变量light指向head中刚刚建立完成的Light对象
c)构造函数中避免含有大量代码,继承层次不宜太深!
d)对象只有在被需要的时候创建出来:
//这段代码中包含了不必要的开销,result这个数组和iae的异常不会同时出现,所以没必要先new出来
public int[] addEach(int[] arr1, int[] arr2) {
int[] result = new int[10];
IllegalArgumentException iae = new IllegalArgumentException("array index is invalid");
if (arr1 != null && arr2 != null && arr1.length == 10 && arr2.length == 10) {
for (int i = 0; i < 10; i++) {
result[i] = arr1[i]+arr2[i];
}
}else{
throw iae;
}
return result;
}
优化的代码可以是:
//在需要是new出对象,可以减少系统对于new对象的高昂代价
public int[] addEach(int[] arr1, int[] arr2) {
if (arr1 != null && arr2 != null && arr1.length == 10 && arr2.length == 10) {
for (int i = 0; i < 10; i++) {
int[] result = new int[10];
result[i] = arr1[i]+arr2[i];
return result;
}
}
throw new IllegalArgumentException("array index is invalid");
}
e)将同步化(synchronization)降至最低
如果你写了一个单线程应用程序,却调用了为多线程访问而设计的函数库中的synchronized方法。在这种情况下完全可以不需要为单线程程序而获取/释放锁,想要消除这种无谓的同步,有两种方式:
i> 提供一个subclass,内含那些函数的unsynchronized 版本
ii> 使用另一个class,提供unsynchronized 函数
例如Vector中大部分方法都是synchronized方法,而ArrayList就是一个提供unsynchronized的方法的类
f)实例对象中变量初始化一次就好
i> Java对于instance变量(null),static变量和arrays都进行了缺省的初始化,我们不需要为这些变量重复设置为其缺省值。
ii> 只有类的变量才有缺省值,局部变量是没有缺省值的!
g)尽量使用基本类型使代码更小更快
基本类型直接从栈中访问,而类类型需要访问堆中。但有时迫不得已必须要使用Integer等来封装基本类型,例如需要将一个整数存放在Vector(或者别的什么集合类-collections)中时,集合类只接受Object,而不接受基本类型,因此迫不得已需要封装
h)不要使用Enumeration 或Iterator来遍历Vector
Java提供了4中变量Vector的方法:
i> Iterator (迭代器)
ii> ListIterator (list迭代器)
iii> Enumeration (枚举器)
iV> get()函数 (取值函数,getter)
class Test {
public int enumVec(Vector v) {
Enumeration myEnum = v.elements();
int total = 0;
while (myEnum.hasMoreElements()) {
total += ((Integer) (myEnum.nextElement())).intValue();
}
return total;
}
public int iterVec(Vector v) {
Iterator iter = v.iterator();
int total = 0;
while (iter.hasNext()) {
total += ((Integer) (iter.next())).intValue();
}
return total;
}
public int ListIterVec(Vector v) {
ListIterator listIter = v.listIterator();
int total = 0;
while (listIter.hasNext()) {
total += ((Integer) (listIter.next())).intValue();
}
return total;
}
public int getVec(Vector v) {
int size = v.size();
int total = 0;
for (int i = 0; i < size; i++) {
total += ((Integer) (v.get(i))).intValue();
}
return total;
}
}
其中代码的执行速度getVec > Enum > Iterator
I)使用System.arraycopy()来复制arrays
arraycopy()函数是native函数,在不同的平台执行的效率有所不同
J)优先使用array,然后才考虑Vector和ArrayList
public void iterateArray(int[] arr){
int size = arr.length;
int j;
for (int i = 0; i < size; i++) {
j = arr[i];
}
}
public void iterateVector(Vector v){
int size = v.size();
Object j;
for (int i = 0; i < size; i++) {
j = v.get(i);
}
}
使用array遍历要比Vector遍历快上40倍,如果Vector中使用Iterator或者Enumeration遍历,则会更慢
首先Vector中所有的方法都是synchronized,其次使用Vector无论何时都必须采用方法调用。尽管ArrayList基本上是个unsynchronized的Vector,但仍然要比array慢上10倍左右。ArrayList和Vector底层都是array实现的,当有新元素超出Vector界限的时候,Vector的实现是创建一个新的数组,将原先数组中的元素复制到这个新的数组中,然后加入原本放不下的那些元素。另外Vector和ArrayList在删除某个元素的时候,所有下标大于被删元素的元素都要向前移动一格,但这样的操作非常的费时。当迫不得已需要使用Vector或者ArrayList时,可以通过[禁止从头部移除]或[禁止在无额外空间的情况下增加元素]等方法来优化Vector的性能
备注:不要仅仅因为手上有个数不定的数据需要存储,就毫无选择的使用Vector或ArrayList。可以考虑创建一个足够大的数组,通常这样可能会浪费内存,但性能上的收益可能超过内存方面的代价。
K)尽可能复用创建出来的对象,来减少创建无谓对象所带来的开销
L)编译为native code:将程序的某部分编译为本地代码,然后通过JNI来访问