最近笔者为了促进开发人员对于SonarQube扫描出的缺陷的重视程度,准备陆续整理了一些典型的问题。首先整理的是关于Null的几个问题,供读者参考。
由于考虑到不能直接贴公司源码,首先选用了SonarQube为规则提供的示例代码,如果没有,就自己按照翻车现场编写了伪代码,可能也不是很贴切。欢迎读者留言提供更多和更为典型的案例。我会继续更新下去。
1 Null pointers should not be dereferenced
@CheckForNull
String getName(){...}
public boolean isNameEmpty() {
return getName().length() == 0;
// Noncompliant; the result of getName() could be null, but isn't null-checked
}
@CheckForNull只是一个提醒哦。
Connection conn = null;
Statement stmt = null;
try{
conn = DriverManager.getConnection(DB_URL,USER,PASS);
stmt = conn.createStatement();
// ...
}catch(Exception e){
e.printStackTrace();
}finally{
stmt.close(); // Noncompliant; stmt could be null if an exception was thrown in the try{} block
conn.close(); // Noncompliant; conn could be null if an exception was thrown
}
并不是有了finally就可以高枕无忧了。
2 Conditionally executed blocks should be reachable
这个案例的问题是对于Null的问题的反例,虽然写了对于null的处理,但是这段代码是不会被执行的。
Response rsp= Httputil.doSomeQuery(url)
if (rsp==null) { // Noncompliant
doSomething(); // never executed
}
在项目中,由于此处的rsp无论如何都不会是Null,因此底下的额外代码属于永远不会被执行的废代码。
3 Call to equals(null)
public void checkResponse(Response rsp)
if (rsp.equals(null)) { // Noncompliant
doSomething(); // 翻车
} else{
//...
}
在上述代码中,如果rsp不为null, 那么rsp.equals(null)一定只会返回false。而如果rsp是null的话,这行代码将会抛出NullPointerException。
因此,正确地进行Null的判断应该使用==,而不是equals。
4 Nullcheck of value previously dereferenced
还是以上述代码为案例,这里的问题是一目了然的。这位开发同学在写代码的时候搞反了两个判断的顺序。如果rsp是null的话,NullPointerException异常又来了。
public void checkResponse(Response rsp)
if (rsp.getErrorCode()==0 || null !=rsp)) { // Noncompliant
doSomething();
} else{
//...
}
5 Method call passes null for nonnull parameter
这个问题也是一个逻辑错误导致的。例如
public boolean accept(String name) {
String result = null;
if (name == "张三") {
result = "zhangsan";
} else if (name == "李四") {
result = "lisi";
}
return result.size() //翻车
}
这里如果name 既不是张三,也不是李四,由于程序员忘记了赋一个默认值,导致了有可能result还是null, 抛异常。
6 Possible null pointer dereference in method on exception path
沿用之前数据库连接的案例。
Connection conn = null;
Statement stmt = null;
try{
conn = DriverManager.getConnection(DB_URL,USER,PASS);
stmt = conn.createStatement();
// ...
}catch(Exception e){
e.printStackTrace();
stmt.close(); // Noncompliant; stmt could be null if an exception was thrown in the try{} block
conn.close(); // Noncompliant; conn could be null if an exception was thrown
}
这是新手程序员常见地在catch中关闭资源。但是由于某些异常,stmt还是null。
网友评论