关于Null的翻车现场

2020-01-11  本文已影响0人  antony已经被占用

最近笔者为了促进开发人员对于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。

上一篇 下一篇

猜你喜欢

热点阅读