总结我们在开发中常见的代码问题,同时将sonar中的问题也归纳了进来
一、异常处理中的未打印或者抛出异常信息
这个主要是没有将异常信息打印出来,又或者异常没有抛出。比如我们在action中,异常信息是打印成日志,而service中是将异常信息抛出,按照这样做了,就不会再有这类的错误。
l Sonar
Either log or rethrow this exception. |
l 错误示例
略
l 处理方案
将异常通过日志打印或者抛出
二、使用非同步的类来代替同步的类
非同步的类在执行效率上会高于同步的类,所以在不是必须同步的情况下,建议使用非同步类。
l Sonar
Replace the synchronized class "StringBuffer" by an unsynchronized one such as "StringBuilder". |
l 错误示例
略
l 处理方案
ArrayList or LinkedList instead of Vector Deque instead of Stack HashMap instead of Hashtable StringBuilder instead of StringBuffer |
三、移除没有用到的包、变量、方法
l Sonar
Remove this useless assignment to local variable xxx |
l 错误示例
略
l 处理方案
移除无用的代码
四、增加有效注释,移除无用注释
我们在开发中,需要增加有效注释,移除无用的无效注释。有时候,在修改代码的时候也会将以前的代码进行注释,防止下次修改的时候再拿来参考或者使用。这个也不推荐,因为时间长了,这类的僵尸代码也比较难清除,并且影响代码的阅读
l Sonar
This block of commented-out lines of code should be removed. |
l 错误示例
略
l 处理方案
移除无用的注释
五、继承的方法需要添加@Override
l Sonar
Add the "@Override" annotation above this method signature |
l 错误示例
略
l 处理方案
在方法上方添加 @Override
六、嵌套不要超过三层
在写代码的时候,if/for/while/switch/try等代码的嵌套层数建议不要超过3层。当超过3层之后,代码的可读性和可维护性都会变的很差,同时如果做单测也会变的很艰难。
l Sonar
Refactor this code to not nest more than 3 if/for/while/switch/try statements. |
l 错误示例
if (condition1) { // Compliant - depth = 1 /* ... */ if (condition2) { // Compliant - depth = 2 /* ... */ for(int i = 0; i < 10; i++) { // Compliant - depth = 3, not exceeding the limit /* ... */ if (condition4) { // Noncompliant - depth = 4 if (condition5) { // Depth = 5, exceeding the limit, but issues are only reported on depth = 4 /* ... */ } return; } } } } |
l 处理方案
减少嵌套层数
七、方法块的圈复杂度过高
l Sonar
The Cyclomatic Complexity of this method xxx is 11 which is greater than 10 authorized. |
l 错误示例
略
l 处理方案
减少嵌套,减少代码行数,避免一个方法过于冗长和沉重,提高阅读性和可维护性。
八、应合并可折叠的if语句
l Sonar
Merge this if statement with the enclosing one. |
l 错误示例
if (file != null) { if (file.isFile() || file.isDirectory()) { /* ... */ } } |
l 处理方案
if (file != null && isFileOrDirectory(file)) { /* ... */ }
private static boolean isFileOrDirectory(File file) { return file.isFile() || file.isDirectory(); } |
九、集合的是否为空集合的判断
在java的一些api中,提供了类似字符串、集合等常见对象的取值和判断的方法,我们要加以运用。
l Sonar
Use isEmpty() to check whether the collection is empty or not. |
l 错误示例
if (myCollection.size() == 0) { // Noncompliant /* ... */ } |
l 处理方案
if (myCollection.isEmpty()) { // Compliant /* ... */ } |
十、整形/长整形转字符串的方法
在java的一些api中,提供了类似字符串、集合等常见对象的取值和判断的方法,我们要加以运用。
l Sonar
Use "Long.toString" instead. |
l 错误示例
int myInt = 4; String myIntString = new Integer(myInt).toString(); // Noncompliant; creates & discards an Integer object myIntString = Integer.valueOf(myInt).toString(); // Noncompliant myIntString = 4 + ""; // Noncompliant |
l 处理方案
int myInt = 4; String myIntString = Integer.toString(myInt); |
十一、 BigDecimal的取值方法
在java的一些api中,提供了类似字符串、集合等常见对象的取值和判断的方法,我们要加以运用。
l Sonar
Use "BigDecimal.valueOf" instead. |
l 错误示例
double d = 1.1;
BigDecimal bd1 = new BigDecimal(d); // Noncompliant; see comment above BigDecimal bd2 = new BigDecimal(1.1); // Noncompliant; same result |
l 处理方案
double d = 1.1;
BigDecimal bd1 = BigDecimal.valueOf(d); BigDecimal bd2 = BigDecimal.valueOf(1.1); |
十二、 使用新的变量来代替传入的变量
方法中传入的变量,一般情况下,我们认为是不可修改的,一旦可修改的话,在测试的时候不容易发现问题是调用方发生的错误还是方法本身发生的错误,这也是有的方法的传入参数为什么要定义为final类型的原因。
l Sonar
Use isEmpty() to check whether the collection is empty or not. |
l 错误示例
class MyClass { public String name;
public MyClass(String name) { name = name; // Noncompliant - useless identity assignment }
public int add(int a, int b) { a = a + b; // Noncompliant
/* additional logic */
return a; // Seems like the parameter is returned as is, what is the point? }
public static void main(String[] args) { MyClass foo = new MyClass(); int a = 40; int b = 2; foo.add(a, b); // Variable "a" will still hold 40 after this call } } |
l 处理方案
class MyClass { public String name;
public MyClass(String name) { this.name = name; // Compliant }
public int add(int a, int b) { return a + b; // Compliant }
public static void main(String[] args) { MyClass foo = new MyClass(); int a = 40; int b = 2; foo.add(a, b); } }} |
十三、 使用正确的类型转换方法
类型转换的方法有很多种方式,我们需要使用更合适的。
l Sonar
Use "Integer.parseInt" for this string-to-int conversion |
l 错误示例
String myNum = "12.2";
float f = new Float(myNum).floatValue(); // Noncompliant; creates & discards a Float |
l 处理方案
String myNum = "12.2";
float f = Float.parseFloat(myNum); |
十四、 不要使用System.out或者System.err
避免使用System.out和Sytem.err,而使用日志的方式输出,同时注意日志的级别,如果只是自己调试使用的话,不要使用Info以上的级别,使用debug就可以了。
l Sonar
Replace this usage of System.out or System.err by a logger. |
l 错误示例
System.out.println("My Message"); // Noncompliant |
l 处理方案
logger.info("My Message"); |
十五、 字符串比较的左边放常量,右边放变量
l Sonar
Move the "0" string literal on the left side of this string comparison. |
l 错误示例
String myString = null;
System.out.println("Equal? " + myString.equals("foo")); // Noncompliant - will raise a NPE System.out.println("Equal? " + (myString != null && myString.equals("foo"))); // Noncompliant - null check could be removed |
l 处理方案
System.out.println("Equal?" + "foo".equals(myString)); // Compliant - properly deals with the null case |