优秀代码准则:
- 简练
- 可读性强
- 模块化
- 层次性
- 设计良好
- 高效
- 优雅
- 清晰
代码规范
- 基本要求
-
- 程序结构清晰,简单一动,单个函数的程序行数不得超过100行
- 打算干什么,要简单,直接了当,代码精简,避免垃圾程序
- 尽量使用标准库函数和公共函数
- 不要随意定义全局变量,尽量使用局部变量
- 使用括号以避免二义性
- 可读性要求
-
- 可读性第一,效率第二
- 保持注释与代码完全一致
- 每个源程序文件,都有文件头说明
- 每个函数都有函数头说明
- 主要变量定义或引用似,注释能反映其含义
- 常量定义有相应的说明
- 处理过程的每个阶段都有相关注释说明
- 在典型算法前也要有注释
- 利用缩进来显示程序的逻辑结构,缩进量一致并以Tab键为单位,定义Tab为6个字节
- 循环,分支层次不要超过五层
- 注释可以与语句同行,也可以在上一行
- 空行和空白字符也算是一种特殊的注释
- 一目了然的语句不用加注释
- 注释的作用范围:定义,引用,条件分支以及一段代码
- 注释行数占总行数的1/5—1/3
- 结构化要求
-
- 禁止出现两条等价的支路
- 用case实现多路分支
- 避免从循环引出多个出口
- 函数只有一个出口
- 不使用条件赋值语句
- 避免不必要的分支
- 不要轻易用条件分支去替换逻辑表达式
- 正确性与容错性要求
-
- 程序首先是正确,其次是优美
- 无法证明你的程序没有错误,因此在编写完一段程序后,应先回头检查
- 改一个错误时可能产生新的错误,因此在修改前首先考虑对其他程序的影响
- 所以变量在调用前必须被初始化
- 对所有的用户输入,必须进行合法性检查
- 不要比浮点数的相等,如:10.0*.01==1.0
- 程序与环境或状态发生关系时,必须主动去处理发生的意外事件,如文件能否逻辑锁定,打印机是否联机等
- 单元测试也是变成的一部分,提交联调测试程序必须通过单元测试
- 可重用性要求
-
- 重复使用的完成相对独立功能的算法或代码应抽象为公共控件或类
- 公共控件或类应考虑面向对象思想,减少外界联系,考虑独立性或封装性
程序性能测试
- 计算性能
例:
public interface Testing(){
public void testArrayList();
public void testLinkedList();
}
public class TextingImpl imlements Testing{
private List link = new LinkedList();
private List array = new ArrayList();
public TestingImpl(){
for(int i = 0;i<10000;i++){
array.add(new Integer(i));
link.add(new Integer(i));
}
}
public void testArrayList(){
for(int i=0;i<10000;i++){
array.get(i);
}
}
public void testLinkedList(){
fot(int i=0;i<10000;i++){
link.get(i);
}
}
}
public class Handler implements InvocationHandler{
private Object obj;
public Hnadler(Object obj){
this.obj = obj;
}
public static Object newInstance(Obeject obj){
Object result = Proxy.newProxyInstance(obj.getClass().getClassLoader().obj.getClass().getInterfaces(),new Handler(obj));
return(result);
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
Object result;
try{
Log.i("Handler","begin method"+method.getName());
long start = System.currentTimeMills();
result = method.invoke(obj,args);
long end = System.currentTimeMills();
Log.i("Handler","the method"+method.getName()+"lasts "+(end - start) + "ms");
}catch(InvocationTargetException e){
throw e.getTargetException();
}catch(Exception e){
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}finally{
Log.i("Handler","end method" + method.getName());
}
return result;
}
}
在创建测试程序中添加:
try{
Testing testing = (Testing)Handler.newInstance(new TestingImpl());
testing.testArrayList();
testing.testLinkedList();
}catch(Exception e){
e.printStackTrace();
}
- 内存消耗
例:
public interface MemoConsumer{
public void createArray();
public void createHashMap();
}
public class MemoConsumerImpl implements MemoConsumer{
ArrayList arr = null;
HashMap hash = null;
public void CreateArray(){
arr = new ArrayList(1000);
}
public void createHashMap(){
hash = new HashMap(1000);
}
}
public class Memory{
public static long used(){
long total = Runtime.getRuntime().totalMemory();
long free = Runtime.getRuntime().freeMemory();
return (total - free);
}
}
public class Handler implements InvocationHandler{
Object result = Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInstances(),new Handler(obj));
return result;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
Object result;
try{
Log.i("Handler","begin method " + method.getName());
long start = Memory.used();
result = method.invoke(obj,args);
long end = Memory.uesed();
Log.i("Handler","memory increased byt " + (end - start) + "bytes");
}catch(InvocationTargetException e){
throw e.getTargetException();
}catch(Exception e){
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}finally{
Log.i("Handler","end method " + method.getName());
}
return result;
}
在Activity01.java中添加如下代码:
MemoConsumer arrayMemo = (MemoConsumer)Handler.newInstance(new MemoConsumerImpl());
arrayMemo.creatArray();
arrayMemo.creatHashMap();
- 启动时间
- 可伸缩性(程序乳液应对增长的流量)
- 用户察觉性能
初级优化
- 尽量指定类的final对象修饰符。
- 尽量重复对象。
- 尽量使用局部变量。
- 不要重复初始化变量。
- Java + Oracle 的开发中,java中内嵌的SQL语句尽量使用大写的形式,以减轻Oracle解析的负担。
- 进行数据连接,I/O流操作完毕后要及时释放资源。
- 对象不再被使用时,手动设置为null,容易被JVM垃圾回收。
- 在使用同步机制时,尽量使用同步方法替代同步块。
- 尽量计算纳税对变量的重复计算。
- 尽量采用lazy loading策略,在需要的时候才开始创建。
- 慎用一场,异常对性能不利。异常只能用于错误处理,不应用来控制程序流程。
- 不要在循环中使用try/catch,应该放置在最外层。
- 使用适合的容量值初始化StringBuffer。
- 合理使用Java.util.Vector,类似StringBuffer成倍数扩展到一维数组。
- 当复制大量数据时,使用System.arraycopy()命令。
- 代码重构,增强代码的可读性。
- 不用new关键字创建类的实例。
- 乘法和除法。
例:
for(val = 0; val <100000;val +=5){
alterX = val *8;
myResult = val*2;
}
改为:
for(val = 0; val <100000;val +=5){
alterX = val << 3;
myResult = val << 1;
}
- 不要将数组声明为:public static final.
- HashMapde的遍历。
for(Entry<String,String[]> entry : paraMap.entrySet()){
String appFieldDefId = entry.getKey();
String[] values = entry.getValue();
}
- array(数组)和ArrayList的使用。数组最高效,但容量是固定的。ArrayList容量可增长,牺牲效率。
- 尽量使用HashMap和ArrayList,除非必要,否则不推荐使用HashTable和Vector,后者由于使用同步机制导致性能开销较大。
- StringBuffer和StringBuilder的区别在于:java.lang.StringBuffer线程安全的可变字符序列。一类于String的字符串缓冲区,但不能修改。StringBuilder与该类相比,通常应该优先使用java.lang.StringBuilder类,因为它支持所有喜爱功能同操作,但由于它不执行同步,所以速度更快。为了获取更好的性能,在构造StringBuffer或StringBuilder时应尽量可能指定它的容量。如果操作的字符串长度不超过16个字符时就不用了。相同情况下,使用StringBuilder比使用StringBuffer仅能获得10%~15%左右的性能提升,但却要冒多线程不安全的风险。而现在的模块化编程中,负责某一模块的程序员不一定能清晰地判断模块是否会放入多线程的环境中运行,因此推荐使用StringBuffer。
高级优化
- 优化循环,通过冲虚组织重复的子表达式来提高循环体的运行性能。
- 减少使用对象的数量来提高运行性能。
- 缩减网络传输数据来缩短等待的时间。
- 采用对象池技术,提高对象的利用率。
在需要创建对象时从对象池获取一个未被使用的对象并用reset()初始化,需要释放对象的似乎猪需要将标志位修改以供下次使用。
- 局部使用基本类型数据代替对象,节省资源开销。
- 用简单的数值计算代替复杂的函数计算,节省处理器时间。
Android高效开发
基本原则
- 不要做不必要做的事
- 尽可能地节省内存的使用
原则
- 尽可能避免创建对象(Object)
-
- 当从原始的输入数据中提取字符时,试着从原始字符串返回一个子字符串,而不是创建一份复本。将会创建一个新的字符串对象,但是它和你的原始数据共享数据空间。
- 如果有一个返回字符串的方法,返回的结果是StringBuffer,改变函数的定义和执行,让函数直接返回而不是通过创建一个临时对象。
- 一个Int类型的数组比一个Integer类型的数组要好,以此类推。
- 创建一个包含一系列Fool和Bar对象的容器时候,两个平行的Foo[]和Bar[]要比一个(Foo,Bar)对象数组的效率高得多。
- 使用自身的方法
- 使用虚拟优于接口
- 使用静态优于使用虚拟
- 尽可能避免使用内在的Get,Set方法
- 缓冲属性带用,减少重复的判断
- 声明常量final
- 慎重使用增强型For循环语句
- 避免列举类型
- 通过内联类使用包空间
- 避免浮点类型的使用
Android UI XML优化
<viewStub/>
使UI在特殊情况下,直观效果类似于设置View的不可见性,但是其更大的R意义在于被这个标签所包裹的View在默认状态下不会占用任何内存空间,visibility=GONE。viewstub通过方法inflate()来召唤系统加载系统加载其内部的View。
<ViewStub
android:id="@+id/stub"
android:inflatedId="@+id/subTree"
android:layout="@layout/mySubTree"
android:layout_width="120dip"
android:layout_height=40dip"
/>
<include/>
通过这个标签直接加载外部的xml到当前结构中,是复用UI资源的常用标签。用法是将需要服用xml文件路径赋予include标签的layout属性。
<include
android:id="@+id/cell1"
android:layout="@layout/ar01"
/>
<include
android:layout_width="fill_parent"
android:layout="@layout/ar02"
/>
<requestFocus/>
用于指定屏幕内的焦点View。用法是将标签至于View的内部.
<EditeText
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingBottom="4"
/>
<requestFocus/>
</EditeText>
<merge/>
目的是通过删减多余或者额外的层级,从而优化整个layout结构。
<merge xmlns:android="http://schemas.android.com.apk/res/android">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
android:src="@drawable/golden_gate"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dip"
android:layout_gravity="center_horizontal|bottom"
android:padding="12dip"
android:background="AA000000"
android:textColor="fff"
adnroid:text="Golden Gate"
/>
</merge>
【注】此标签只可以作为xml layout的根节点。当需要扩展到xml layout本身是由merge作为根节点的话,需要将被导入的xml layout置于viewGroup中,同时需要设置attachToRoot为True。