好习惯是成功的一半。因为,你知道,“任何可能出错的事情都会出错。”这就是人们喜欢做“防错编程”的原因。下面我列出了我个人认为最有用但偏执的10个Java编程技巧。参见:1.把字符串常量放在前面(技术文本)把字符串常量放在比较函数equals()的左边,这样可以防止意外的NullPointerExceptions,像这样://Badif(variable.equals("literal")){...}//Goodif("literal".equals(variable)){...}毫无疑问,将一个表达式转换为另一个更好的表达式,没有任何损失。只要我们的Options是真实的(Java8中的Optional是对可以为空的对象的封装),不是吗?讨论...2.不要相信早期的JDKAPIJava刚出现的时候,编程一定是一件痛苦的事情。当时API还不成熟,你可能遇到过这样一段代码:String[]files=file.list();//注意if(files!=null){for(inti=0;i=0){...}谁知道。也许在特定情况下他们需要另一个编码值,如果不区分大小写,otherString将被包括在内...此时可能返回-2?谁知道呢。之后总之,我们有很多关于NULL的错误——价值数十亿(https://blog.jooq.org/2015/07/22/null-is-not-the-billion-dollar-mistake-a-counter-rant/)。为什么不开始讨论-1,某种意义上-1是int类型下null的另一种形式。4.避免意外赋值(技术)是的。即使是最优秀的程序员也会犯这个错误(当然,不包括我。见#7)。(假设这是JavaScript,让我们暂时偏执)//Ooopsif(variable=5){...}//更好(因为会导致错误)if(5=variable){...}//Intent(记住.偏执的JavaScript:===)if(5===variable){...}再说一遍。如果你的表达式中有一个常数,把它放在等式的左边。这使得当您尝试添加另一个=时更不容易出错。5.检查空值和长度每当你有一个集合、数组或其他任何东西时,确保它存在并且不为空。//Badif(array.length>0){...}//Goodif(array!=null&&array.length>0){...}你不知道这些数组是从哪里来的,可能是早期的JDK应用程序接口?6.所有方法都使用final声明(技术文本)你可以告诉我你想要的任何开闭原则,但那是废话。我不相信你(正确地继承我的班级),也不相信我自己(不意外地继承我的班级)。因此,除了接口(特别是用于继承)之外的所有内容都应该是严格最终的。请参阅我们的Java编码的10个精妙最佳实践中的第9条。//Badpublicvoidboom(){...}//很好。不要碰。publicfinalvoiddontTouch(){...}对,写成final。如果这样做对您没有意义,您还可以通过修改或重写字节码来更改类和方法,或者发送功能请求。我很确定覆盖类/方法不是一个好主意。7.重载时不要相信泛型(技术)是的,它发生了。您认为您已经编写了一个很棒的AP??I,它非常酷且直观;然后有一群用户只是将所有类型都死记硬背到Object中,直到该死的编译器停止工作,然后他们突然链接错了,认为这都是你的错(总是这样)。想想这个://Badvoidbad(Tvalue){bad(Collections.singletonList(value));}voidbad(Listvalues){...}//Goodfinalvoidgood(finalTvalue){if(valueinstanceofList)good((List>)value);elsegood(Collections.singletonList(value));}finalvoidgood(finalListvalues){...}因为,你知道...你的用户,他们是这样的//Thislibrarysucks@SuppressWarnings("all")Objectt=(Object)(List)Arrays.asList("abc");不好(t);相信我,我见过很多这样的事,而这个偏执的人得到了回报。8.Alwaysadddefault(好技术文)切换到switch语句...作为最搞笑的表达方式之一,不知道是敬畏还是默默流泪。不管怎样,既然我们不能去掉switch,那么我们可以在必要的时候正确使用它,例如://Badswitch(value){case1:foo();中断;案例2:bar();break;}//Goodswitch(值){案例1:foo();中断;案例2:bar();break;default:thrownewThreadDeath("That'llteachthem");}因为当value=3被引入到软件中时,default可以起到作用,使其正常运行!不要向我提及枚举类型,因为这同样适用于枚举。9.用大括号分隔switch的每个case块(技术文)其实switch是最笨的语句,喝醉了或者赌输了的人都可以在某种语言中使用它。看看这个例子://Bad,doesn'tcompileswitch(value){case1:intj=1;休息;情况2:intj=2;break;}//Goodswitch(value){case1:{finalintj=1;break;}case2:{finalintj=2;break;}//记住:默认:thrownewThreadDeath("That'llteachthem");}在switch语句中,对于所有Cases只定义一个范围。其实这些case并不是真正的语句,它们更像是标签,而switch就是指向这些标签的goto语句。事实上,您甚至可以将case语句与令人惊叹的FORTRAN77语句进行比较。对于FORTRAN,它的神秘已经超越了它的功能。这意味着无论是否有break,变量finalintj都可以被任何case访问。看起来不是很直观。我们可以通过添加简单的大括号为每个case创建一个新的嵌套作用域,当然不要忘记在每个case的语句块中添加一个break。