(1)StringBuffer的使用
这一条和Java中的优化规则一样,例如当需要对一组String进行连接时,请不要使用下面的代码。
而是应当写成:
如果知道StringBuffer的最大长度,请使用最大数字。例如,在上面的代码中,StringBuffer的最大长度设置为50,这使得在使用StringBuffer的过程中,不需要考虑自增长问题。
(2)声明Final常量
请读者看下面一个类的顶部声明:
当第一次使用一个类时,编译器会调用一个类初始化方法:<clinit>()。这个方法将42存入变量intVal中,并且为strVal在类文件字符串常量表中提取一个引用,当这些值在后面引用时,就会直接访问。我们可以用关键字“final”来改进代码:
这样此类将不会调用<clinit>()方法,因为这些常量直接写入了类文件静态属性初始化中,这个初始化直接由虚拟机来处理。当代码访问intVal时,将会使用Integer类型的42;当访问strVal时,将会使用相对节省的“字符串常量”来替代一个属性调用。
如果将一个类或者方法声明为“final”,并不会带来任何的执行上的好处,它能够进行一定的最优化处理。例如,如果编译器知道一个get方法不能被子类重载,那么它就把该函数设置成inline。
同时,我们也可以把本地变量声明为final变量。但是这是毫无意义的。作为一个本地变量,使用final只能使代码更加清晰(或者你不得不用,在匿名访问内联类时)。
(3)避免使用枚举
枚举变量非常方便,但是这是以牺牲执行的速度和大幅增加文件体积为前提的。例如下面的演示代码:(www.daowen.com)
上述代码会产生一个900字节的.class文件(Foo$Shubbery.class)。在它被首次调用时,这个类会调用初始化方法来准备每个枚举变量。每个枚举项都会被声明成一个静态变量,并被赋值。然后将这些静态变量放在一个名为“$VALUES”的静态数组变量中。而这么一大堆代码,也仅仅是为了使用三个整数。
这样下面的代码会引起一个对静态变量的引用,如果这个静态变量是final int,那么编译器会直接内联这个常数。
一方面说,使用枚举变量可以让API更出色,并能提供编译时的检查。所以通常应该为公共API选择枚举变量。但是当性能方面有所限制的时候,就应该避免这种做法了。在有些情况下,使用方法ordinal()获取枚举变量的整数值会更好一些,举例来说,如果将:
替换为:
这样会使性能得到一些改善,但这并不是最终的解决之道。
如果将与内部类一同使用的变量声明在包范围内,即下面的类定义:
这其中的关键是,定义了一个内部类(Foo$Inner),它需要访问外部类的私有域变量和函数。这是合法的,并且会打印出期望的结果:
但问题是,在技术上来讲,Foo$Inner是一个完全独立的类,它要直接访问Foo的私有成员是非法的。要跨越这个鸿沟,编译器需要生成一组方法:
当内部类在每次访问“mValue”和“doStuff”方法时,都会调用这些静态方法。也就是说,上面的代码说明了一个问题,即通过接口方法访问这些成员变量和函数而不是直接调用它们。在前面已经说过,使用接口方法(getter、setter)比直接访问速度要慢。所以这个例子就是在特定语法下面产生的一个“隐性的”性能障碍。
通过将内部类访问的变量和函数声明由私有范围改为包范围,可以避免这个问题。这样做可以让代码运行更快,并且避免产生额外的静态方法。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。