由于考试的原因,好长时间都没能来写博文了(什么时候出的CSDN-markdown编辑器),今天就代码优化方面来写一篇博文,主要是讲Java。
优秀代码具备的品质:
1.简练
2.可读性强
3.模块化
4.层次性
5.设计良好
花些时间设计你的程序,因为思考的代价要小于调试。
6.高效
7.清晰
清晰是优秀代码的基本。
常见的编程规范:
1.基本要求
*程序结构清晰,简单易懂,单个函数的程序行数最好不超过100行。
*尽量使用标准的函数和公共函数。
*不要随意的定义全局变量,尽量使用局部变量。
*使用括号以避免二义性。
2.可读性的要求
*可读性第一,效率第二。
*保持注释与代码完全一致。
*每个源程序文件,都有头文件说明。
*每个函数,都有函数头说明。
*主要变量定义或引用时,注意能反应其含义。
*常量定义有相应注释说明。
*利用缩进来显示程序的逻辑结构,缩进量一致并以Tab键为单位。
3.结构化要求
*避免从循环引出多个出口。
*函数只有一个出口。
*不使用条件赋值语句。
*不要轻易用条件分支去替换逻辑表达式。
4.正确性与容错性要求。
*程序首先是正确,其次是优美。
*改一个错误时可能产生新的错误,因此在修改前首先考虑对其他程序的影响。
*对所有的用户输入,必须进行合法性的检查。
*不要比较浮点数的相等。如:
10.0*0.1==1.0
5.可重用行要求
*重复使用的完成相对独立功能的算法或代码应抽象为公共控件或类。
*公共控件或类应考虑面向对象思想,减少外界联系,考虑独立性或封装性
上面说了那么多条条框框,有点疲惫了吧,那么下面就贴近代码来进行讲解吧。
(1)尽量指定类的final修饰符。带有final修饰符的类是不可派生的,也就是不能被继承
。Java编译器会寻找机会内联所有的final方法。此举能够使性能平均提高50%。
(2)尽量重用对象。特别是String对象的使用,出现字符串连接情况时应用StringBuffer代替。
(3)尽量使用局部变量。调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中,易于访问。其他变量,如:静态变量,都在最终创建,访问速度较慢。
(4)在Java+Oracle的应用系统开发中,Java中内嵌的SQL语句尽量使用大写的形式,以减轻Oracle解析器的解析负担。
(5)Java编程过程中,进行数据库连接、I/O流操作时务必小心,在使用完毕后,及时关闭以释放资源。
(6)JVM的GC机制。JVM回收垃圾的条件:对象不再被引用;然而,JVM的G并非十分地机制,即使对象满足了垃圾回收的条件也不一定会被立即回收。所以,建议在使用完对象后,手动设置成null。
(7)在使用同步机制时,应尽量使用方法同步代替代码块同步。
(8)尽量减少对变量的重复计算。
列如:
for (int i = 0; i < list.size(); i++) { }
应替换为:
for (int i = 0, size = list.size(); i < size; i++) { }
(9)尽量采用lazy loading(延时加载)的策略,在需要的时候才开始创建。
列如:
String str = "1111"; if (i == 1) { list.add(str); }
应替换为:
if (i == 1) { String str = "1111"; list.add(str); }
(10)不要在循环中使用Try/Catch语句,应把其放置在最外层。
(11)使用一个合适的容量值来初始化StringBuffer。当使用缺省的构造函数来创建StringBuffer对象时,StringBuffer的容量被初始化问你16个字符。当StringBuffer达到最大值时,它会将自身容量增加到当前的2倍在加二。由于String达到它的最大容量,它必须创建一个新的字符数组,将原来的字符复制一遍到新创建的字符数组。
(12)合理地使用Java类java.util.Vector。
由于Vector中各个元素之间不能含有“空隙”。删除除如最后一个元素之外的任意其他元素都会导致被删除元素之后的元素向前移动。
示:
for (int i = 0; i < 10000; i++) { v.remove(0); }
与下面的代码相比,上面的代码要慢的多。
for (int i = 0; i < 10000; i++) { v.remove(v.size()-1); }
从Vector类型的对象中删除所有元素的最好方法:
v.removeAllElements();
下面说说Vector类的对象v中含有字符串“123456”,对“123456”进行删除操作。
示:
String s = "123456"; int i = v.indexOf(s); if (i != -1) { v.remove(s); }
此段代码在性能上是不利的,因为indexOF()方法对v进行了顺序搜索,而remove()方法也进行了顺序搜索。
改进后:
String s = "123456"; int i = v.indexOf(s); if (i != -1) { v.remove(i); }
改进后代码避免了第二次搜索。remove()方法中给出待删除元素的精确索引位置。
最好的实现这个功能:
String s = "123456"; v.remove(s);
关于size()方法,上面(8)说明了使用方法,至于为什么,给出如下代码:
//假如size =100000 for (int i =0;i<v.size();i++) { }
由于size()中有100000个元素,每次循环后都会重新计算一下size的大小,所以要调用100000次v.size()。
(13)当复制大量数据时,使用
System.arraycopy();
(14)不用new关键词创建类的实例。
用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。
在使用设计模式的场合,如果用Factory模式创建对象,则改用clone()方法创建新的对象实例非常的简单。例如,下面是Factory模式的一个典型实现。
public static Test getNewTest(){ return new Test(); }
使用clone()方法:
private static Test test = new Test(); public static Test getNewTest() throws CloneNotSupportedException{ return (Test) test.clone(); }
(15)乘法和除法。用移位操作替代乘法可以极大地提高性能。
示:
for (int i = 0; i < 100000; i+=5) { a = i * 8; b = i * 2; }
修改后:
for (int i = 0; i < 100000; i+=5) { a = i <<3; b = i <<1; }
每左移1位相当于乘以2,每右移1位相当于除以2。
(16)不要将数组声明:public static final
(17)尽量使用HashMap和ArrayList,除非必要,否则不推荐使用HashTable和Vector,后者由于使用同步机制,而导致了性能的开销。
至此此博文接近尾声了。最后提一点在Android开发中java代码的优化。
在Android开发中,尽可能避免使用内在的Get、Set方法。
在Android编程中,虚方法的调用会产生很多代价,比实例属性查询的代价还要多。我们应该在外部调用时使用Get和Set函数,但是在内部调用时,我们应该直接调用。