前言

项目稳定之后,开始逐步关注过去赶进度写的“坏”代码问题,唯品会内部订制的sonar检测规则,在每次上线的时候都会进行静态代码检查,这阵子抽空看了自己项目的代码问题,同时也看了很多别的项目的检测结果,还是挺有收获,记录下。

代码细节

1.boxed and unboxed

拆箱跟装箱,是在sonar检测结果中见过最多的,正如sonar所提示 Be aware that this boxing happens automatically when you might not expect it. 很多没必要的装箱拆箱操作都是在你无意间发生的。比如:

Long data = Long.parseLong("123");

Long.parseLong(XXX) 返回的是long,而结果声明的是Long,所以无意间又触发了装箱
同样,反过来的有valueOf方法

long data = Long.valueOf("123");

这个问题是在看了几个项目的sonar结果中最常见的一个,比较多的场景是在用到方法调用参数上,例如方法的参数声明为 long, 而调用的时候是传Long,这样不仅有拆箱的操作,而且有NPE的可能性。

2.Files.newInputStream(myfile.toPath()) and new FileInputStream

创建FileInputStream对象,在使用new FileInputStream方式中,FileInputStream实现了finalize方法,这意味着创建的对象可能会一直挂起,直到发生gc,这意味着该对象在堆上的垃圾过多的时间更长。在java 7 中提供了NIO方式去创建,

InputStream is = java.nio.file.Files.newInputStream(myfile.toPath()); 

该方法返回的是 new sun.nio.ch.ChannelInputStream, ChannelInputStreamm没有实现finalize方法,就不会有上面那种问题。类似的还有FileOutputStream

3.静态变量和成员变量命名

一个类出现2个或多个变量几乎一样,除了大小写有区分外,可见性、命名几乎一样,这样让用户会感到非常困惑。比如:

private final static String COMMENT = "comment";
private String comment;
public String getComment() {
 return comment;
}
public void setComment(String comment) {
 this.comment = comment;
}

处理的时候建议修改COMMENT变量的名字,因为修改 comment变量会导致破坏调用方。

4.Stream漏了close

在处理输入流的时候大家都会注意在finally块close掉,但是可能会有漏掉的。比如:

InputStream stream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
try {
 ...
 inputStreamReader = new InputStreamReader(stream, "UTF-8");
 reader = new BufferedReader(inputStreamReader);
 ...
} finally {
 if(reader != null){
  reader.close();
 }
}

只close掉 bufferReader,往往就忘记close InputStream 了

5.SimpleDateFormat线程安全问题

在通过静态属性获取SimpleDateFormat的实例进行调用,在使用上会有线程安全问题,本质上是因为parse方法的过程会有一个 Calendar.clear(重置日期对象cal的属性值),在多线程情况下可能会导致A线程 parse过程被B线程clear掉,导致错误。

public class Test {  
  	private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  	public void test() {
  		simpleDateFormat.parse(XXX)
  	}
}

可以每个线程new 一个SimpleDateFormat对象,或者用ThreadLocal,或者直接使用common-lang的工具类。

6.indexOf 单个字符,使用单引号字符

在字符串获取某个字符的index的时候,采用单引号的写法,即字符,会比单字母的字符串效率会更高

addr.indexOf("A")  
addr.indexOf('A')

–未完待续