最近,分析了很多由自动化工具扫描出来的代码漏洞,很多Bug都是因为我们平时写代码不注意规范导致的。更可怕的是很多时候我们并不知道那样写代码有什么问题。 今天就把这些问题总结一下。
1.非空判断
我们在代码中经常这样写:
if(user.getUserName().equals("hollis")){
}
这段代码极有可能在实际运行的时候跑出NullPointerException
。无论是user本身为空,还是user.getUserName()为空,都会抛出异常。 所以,在调用一个参数时要确保他是非空的。
上面的代码可以改为:
if(user!=null&&"hollis".equals(user.getUserName())){
}
还有,我们可能认为在使用增强for循环进行遍历的时候不会产生空指针异常,但是,事实并不是这样的。
for(User user:userList){
}
代码可以不用判断userList是否为空,也不用判断userList.size()==0。 但是,遍历出来的user并不一定不为空。所以,在增强for循环中使用对象时也要最非空判断。
2.有些分支永远不会被运行到
要避免这种代码:
if(true){
}else{
}
else
没有任何意义。
3.流必须要关闭
无论是什么流,都要在finally中显示的关闭。
4.用StringBuffer代替String
在循环中构建一个String对象时从性能上讲使用StringBuffer来代替String对象 例如:
// This is bad
String s = "";
for (int i = 0; i < field.length; ++i) {
s = s + field[i];
}
应该改为StringBuffer
,使用append
方法:
StringBuffer buf = new StringBuffer();
for (int i = 0; i < field.length; ++i) {
buf.append(field[i]);
}
String s = buf.toString();
5.不要调用equals方法比较不同类型的类
6.生产代码中建议不要使用System.out及System.err
7.线上代码禁止printStackTrace!
8.多线程下的安全隐患,须使用final static 修饰,避免多线程环境下对象篡改导致的bug。
9.实例方法写入了静态字段,当实例创建多次时静态字段可能会被改变。
10.实现序列化接口或父类实现序列化接口的 子类都需要声明序列化id!
new ArrayList<String>(){{
add(datasourceKey);
}}
需要添加:private static final long serialVersionUID = 1L;
11.不要在类成员属性中声明simpleDateFormat StringBuilder HashMap 等线程不安全对象!
12.为局部变量赋值,但在其后的没有对她做任何使用。
变量不使用就不要定义 通常,这表明一个错误,因为值从未使用过。
13.不要在方法中对不为空的值进行为空的判断。
14.Switch语句中一个分支执行后又执行了下一个分支。
通常case后面要跟break 或者return语句来跳出。
15.精准度隐患!
double最好不要用来进行计算,应该使用bigDecimal
线上代码禁止printStackTrace!
什么原因啊?