Practical Java(重点版)之性能

 

1. 先把焦点放到设计、数据结构和算法上。

2. 不要依赖编译期优化技术。

编译期优化是指:在调试阶段,把编译优化给关闭掉,当调试完毕后,再打开编译优化让编译优化来选择最便捷的代码,这样程序运行性能就很好。Java编译器对产生优化后的bytecode不是很启作用。

3. 理解运行期(runtime)代码优化技术

4. 要使字符串拼接结合,请尽量使用StringBuffer,而不是String。

String表示建立后的对象,其字符序列不能够再被修改了。

StringBuffer表示建立后的对象,其中的字符序列的值是可以变化的。

5. 将创建对象的成本降到最小。

创建对象所有做到事情,顺序如下:

1.从heap 之中分配内存,用以存放全部的instance 变量以及这个对象连同其superclasses 的实现专届数据(implementation-specific data)。所谓[实现专属数据]包括指向“class and method data”的指针。

2.对象的instance 变量被初始化为其相应的缺省值。

3.调用most derived class(最深层派生类)的构造函数(constructor)。构造函数做的第一件事就是调用superclass 的构造函数。这个程序一直反复持续到java.1ang.object 构造函数被调用为止。一定要记住,java.1ang.object 是一切Java 对象的base class。

4.在构造函数本体执行之前,所有instance 变量的初始值设定(initializers) 和初始化区段(initialization blocks)先获得执行,然后才执行构造函数本体。于是base class 的构造函数最先执行,most derived class 的构造函数最后执行。这使得任何class 的构造函数都能放心大胆地使用其任何superclasses 的instance 变量。

创建对象的过程,举例如下:

public class Light {

   private int val;

   private boolean hasData = true;

 

   public Light(int a) {

      val = a;

   }

 

   public static void main(String[] args) {

      Light lgt = new Light(2);

   }

}

Light 对象的建立步骤如下:

   1.从heap 分配内存,用来存放Light class 的instance 变量,以及一份[实现专属数据]。

   2.此class 的instance 变量val 和hasDate,被初始化为相应缺省值。Val 被赋值为0,这是Int 的缺省值,hasDate 被韧始化为缺省值fa1se。

   3.调用Light 构造函数,传入数值5。

   4.调用Light 构造函数调用其superclass(本例为j ava.1ang.object)的构造函数。

   5.一旦java.1ang.object 构造函数返回,Light构造函数执行其instance 变量的初值设定工作。此时将hasData 赋值为true。

   6.将val 赋值为5,而后Light 构造函数结束。

  7.object reference lgt 指向head 中刚刚建立完成的Light对象。

以下class特征会增加创建对象的成本:

   1. 构造函数含有大量代码;

   2. 内含数量众多的对象;

  3. 继承层次太深。

6. 慎防未用上的对象

在需要的时候才创建对象。

7.将同步化(synchronization)降至最低

   一般情况下,请不要使用synchronized,因为会降低性能。如果不得已的话,请优先将synchronized加在函数上,然后再考虑是否加在函数内部。因为如果你在函数本体中使用synchronized,就会产生操作代码monitorenter 和Moniterexit 的bytecode,以及为了处理异常而附加的代码。

8. 尽可能使用stack变量。

9. 使用static、final 和private 函数以促成inlining(内联)。以函数体替换掉函数调用,性能会增加。一般是小型函数被促成inlining。

10. instance 变量的初始化一次就好.对象的instance变量的默认初始化,在构造方法执行前已经执行力次,所以不需要造次执行。只有class 的static 变量和instance 变量才有缺省值,局部变量是没有缺省值。

11.使用原生态数据类型代码更快更小。

  不要使用Enumeration 或Iterator 来遍历Vector。

  Java提供了以下方式来获取变量vector中的元素:

       a.Interaor遍历器

       b. ListInterator遍历器(只针对List的)

       c. Enumeration(枚举器)

       d. Get函数

12.使用System.arraycopy来复制数组. System.arraycopy()是以本机函数(native method)实现的,因此它的执行速度更快。

13.优先使用数组,然后再考虑使用Vector和ArrayList。Vector和ArrayList底层都是以数组来实现的,而Vector调用的时候都是同步的,并且都要调用其他函数,所以在数组、Vector、ArrayList这三者中,Vector效率最慢。

14.尽可能复用对象。

15.使用缓式评估(延迟求值,lazy evaluation),是一项与语言无关的技术,它会延缓计算,直到不能再拖延为止。工作的推迟当然不会带来性能的提升,但如果被推迟的计算后来不再需要,从而不需执行的话,性能就提升了。也就是说免除了非必要的工作。

16. 以手工的方式将代码优化。Javap –c 便可以反编译.class文件。

Java –c 类(去掉了.class后缀)> test.txt(存储文件),将会产生bytecode。

17. 编译为本机代码。将java 源码编译为目标平台上的本机二进制码(native binary code)。。这种做法并不是把java 源码编译为中介的bytecode 形式.而是直接编译为本机机器指令(native machine instructions)。这样做的好处在于,你不再需要为[运行期间将bytecode 转换为native code 付出额外代价,因而往往获得更快捷的代码。缺点是通常会丢失[平台可移植性]——尽管这或许不是你在意的。面对这个问题,至少有一种解决方案,既不会失去平台可移植性,又享有本机二进制码(native binary code)在执行速度上的优势。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值