前言:不可否认,你对我下面写的这些代码偏执或许感到帮助不大。但我想说的是:做程序开发,自己一定要有一定的坚持,一定的偏执,才能写出好的程序。(偏执可不是固执,你懂的)
继续前言:做人也是需要偏执的,也即一定的坚持。没有了坚持,丢失了原则,自己还给自己找那些冠冕堂皇的理由和借口!是不是很可笑!我最痛恨的就是那些:结婚前,就同居的男男女女!你们现在同居了,假如你们将来各种原因,最后分手了。那等你真正结婚的那一刻,你对的起谁!你难道还拍着胸脯说,我问心无愧,对得起自己的良心!我很愤怒,你对得起你的前任男女友,那对得起结婚后要陪伴你一辈子的丈夫或者妻子吗!!!情绪控制不住,多说了。尽量开心些吧。人活着,好不容易,好多的舍不得。
真正的男女平等,在你丢去一些原则的时候,已经再也没有了平等!种因必得果。好自为之吧。
开篇:大悲无泪,大悟无言,大笑无声
1. 把字符串常量放在前面
/*通过把字符串常量放在比较函数equals()比较项的左侧来防止偶然的 NullPointerException*/
// Bad
if (variable.equals("literal")) { ... }
// Good
if ("literal".equals(variable)) { ... }
2.不要相信早期的JDK APIs
//Bad
String[] files = file.list();
// Watch out
if (files != null) {
for (int i = 0; i < files.length; i++) {
...
}
}
/*“如果抽象路径名表示的不是一个目录,那么这个方法返回null。否则返回一个字符串数组,其中每个字符串表示当前目录下的一个文件或目录。”
因此,最好再加上判空检查,以确保正确*/
//Good
if (file.isDirectory()) {
String[] files = file.list();
// Watch out
if (files != null) {
for (int i = 0; i < files.length; i++) {
...
}
}
}
3. 不要相信“-1”
/*Javadoc中关于 String.indexOf() 的早期描述是这样的…
“字符在字符序列中第一次出现的位置将作为结果[被返回],如果字符不存在则返回-1。”也许在某个特定场合下他们将会需要另一种 编码值,如果不区分大小写的话,otherString 就会被包含进去…此时或许可以返回 -2呢?*/
// Bad
if (string.indexOf(character) != -1) { ... }
// Good
if (string.indexOf(character) >= 0) { ... }
4. 避免意外的赋值
//假设这是JavaScript
// Ooops
if (variable = 5) { ... }
// Better (because causes an error)
if (5 = variable) { ... }
// Intent (remember. Paranoid JavaScript: ===)
if (5 === variable) { ... }
//如果你的表达式中有常量,将它放在等式左边。这样当你打算再添加一个 = 时,不容易出错。
5. 检查null和长度
//不管什么时候你有一个集合、数组或者其他的,确保它存在并且不为空
// Bad
if (array.length > 0) { ... }
// Good
if (array != null && array.length > 0) { ... }
6. 所有的方法都用 final 声明
/*我不相信你(可以正确继承我的类),也不相信我自己(不会意外地继承我的类)。因此除了接口(专门用于继承)都应该是严格的final。*/
// Bad
public void boom() { ... }
// Good. Don't touch.
public final void dontTouch() { ... }
7. 所有的变量和参数都用 final 声明
/*我不相信自己不会无意间重写了某个值。这么说来,我的确一点都不相信自己。因为:这也是为什么所有的变量和参数都用final声明的原因。*/
// Bad
void input(String importantMessage) {
String answer = "...";
answer = importantMessage = "LOL accident";
}
// Good
final void input(final String importantMessage) {
final String answer = "...";
}
8. 重载的时候不要相信泛型
/*把一切类型生搬硬套进 Object 中 直到那该死的编译器停止工作,然后他们突然链接到了错误的方法,认为这一切都是你的错(事情总是这样)。*/
// Bad
<T> void bad(T value) {
bad(Collections.singletonList(value));
}
<T> void bad(List<T> values) {
...
}
// Good
final <T> void good(final T value) {
if (value instanceof List)
good((List<?>) value);
else
good(Collections.singletonList(value));
}
final <T> void good(final List<T> values) {
...
}
9. 总是在switch语句里加上default
// Bad
switch (value) {
case 1: foo(); break;
case 2: bar(); break;
}
// Good
switch (value) {
case 1: foo(); break;
case 2: bar(); break;
default:
throw new ThreadDeath("That'll teach them");
}
10. 用大括号隔开 switch 的每一个 case 块
/*在switch语句中,为所有的case都只定义了一个作用域。事实上,这些case不是真正意义上的语句,他们更像是标签,而switch就是指向这些标签的goto语句。这意味着变量final int j 可以被任何case访问,不论我们是否有break。看起来并不是很直观。我们可以通过添加简单的花括号为每一个case创建一个新的嵌套的作用域,当然不要忘了在每个 case 的语句块最后加 break。*/
// Bad, doesn't compile
switch (value) {
case 1: int j = 1; break;
case 2: int j = 2; break;
}
// Good
switch (value) {
case 1: {
final int j = 1;
break;
}
case 2: {
final int j = 2;
break;
}
// Remember:
default:
throw new ThreadDeath("That'll teach them");
}
结论
编程时的强迫症有时候看起来会很奇怪,会使得代码往往比必需的还要冗长。你可能会想,“啊,这种情况永远不会发生!”,但是正如我所说的,在经历了长时间的编程生涯后,你不会想要再去修正那些只是因为编程语言的古老和固有缺陷而导致的愚蠢而不必要的bug了。因为你知道…..