写简单的代码
1 避免使用自增减表达式(i++,++i,i--,--i)。含有它们的表达式,结果可能取决于求值顺序,所以它可能在某种编译器下能正确运行,换一个编译器就出现离奇的错误。其实这两个表达式完全可以分解成两步,把读和写分开:一步更新i的值,另外一步使用i的值。比如,如果你想写foo(i++),你完全可以把它拆成int t = i;i += 1;foo(t);。如果你想写foo(++i),可以拆成i += 1;foo(i);拆开之后的代码,含义完全一致,却清晰很多。到底更新是在取值之前还是之后,一目了然。
i++或者++i的效率比拆开之后要高,这只是一种错觉。这些代码经过基本的编译器优化之后,生成的机器代码是完全没有区别的。自增减表达式只有在两种情况下才可以安全的使用,比如for(int i=0;;i++)。另一种情况是写成单独的一行,比如i++。这两种情况是完全没有歧义的。需要避免其它的情况,比如用在复杂的表达式里面,比如foo(i++),foo(++i)+foo(i)。
2 不要省略花括号。C,Java都允许在if语句里面只有一句话的时候省略掉花括号:但如果添加代码时容易出错,忘记加花括号。由于花括号的存在,使得代码界限明确,且不易出错。
3合理使用括号,不要盲目依赖操作符优先级。
4避免使用continue和break。循环语句(for,while)里面出现return是没问题的,如果使用了continue或者break,就会让循环的逻辑和终止条件变得复杂,难以确保正确。如果循环里出现了continue或break,应该考虑改写这个循环。
情况1:List goodNames = new ArrayList();
for(String name:names)
if(name.contains("bad"){
continue;
}
goodNames.add(name);
...
}
如果name含有'bad"这个词,跳过循环代码,,这是一种“负面”的描述,它不是在告诉你什么时候“做”一件事,而是在告诉你什么时候“不做”一件事。其实,只要把continue的条件反向,这段代码可以很容易的被转换成等价的,不含continue的代码:
List goodNames = new ArrayList();
for(String name:names)
if(!name.contains("bad"){
goodNames.add(name);
...
}
}
情况2:for和while头部都有一个循环的“终止条件”,本来应该是循环唯一的退出条件。如果在循环中间有break,其实给这个循环增加了一个退出条件,只需要把这个条件合并到循环头部,就可以去掉break。
情况3:很多break退出循环之后,接下来就是一个return。这种break往往可以直接换成return。比如:
public boolean hasBadName{
boolean result = false;
for(String name:names)
if(!name.contains("bad"){
result = true;
.break;
}
}
return result;
}
这个函数可以被改写成:
public boolean hasBadName{
boolean result = false;
for(String name:names)
if(!name.contains("bad"){
ret
}
}
return result;
}
99%的break和continue,都可以通过替换成return语句,或者翻转if条件的方式来消除掉。剩下的1%含有复杂的逻辑,可以通过提取一个帮助函数来消除掉。修改之后的代码变得容易理解,容易确保正确。
1 如果出现了continue,只需要把continue的条件反向,就可以消除continue。
2 如果出现了break,往往可以把break的条件,合并到循环头部的终止条件里,从而去掉break。
3 有时候可以把break替换成return,从而去掉break。
4 如果以上都失败了,可以把循环里面复杂的部分提取出来,做成函数调用,之后continue或者break就可以去掉了。