1.Refactor this method to reduce its Cognitive Complexity from 26 to the 15 allowed.-方法认知复杂度过高。
认知复杂性是衡量一个方法的控制流有多难理解的指标。具有高度认知复杂性的方法将难以维护。
复杂度计算规则
1. &&、|| 条件判断符号+1
2. if,else if,else,switch分支语句+1
3. for、while、do while 循环语句+1
4. catch 捕获异常语句+1
5. break、continue 终端语句+1
6. 如果if、for、while、do while、catch存在嵌套时,里层的语句相对于外层+1
7. sonar要求认知复杂度不能高于15
优化思路
1.针对if,else判断的处理,如果之后没有处理,则在if中直接返回,else无需使用 --优化表达式
2.代码中多层嵌套循环,逻辑重组,将多层循环抽取(明确执行该处代码具体需要满足的条件) --提炼函数
3.减少if,else,for,while,do while,catch关键字嵌套,可以把深层次的代码抽象成方法 --简化代码
4.如果大量使用if-else语句可以考虑用switch代替 --减少认知复杂度
5.判空等操作可以使用工具类,减少||,&&的判断使用
2.String literals should not be duplicated -字符串重复出现3次及3次以上
重复的字符串文字使重构过程容易出错,因为必须确保更新所有出现的内容。另一方面,常量可以从许多地方引用,但只需要在一个地方更新。
新加了一个常量类ConstantStr.java
// Noncompliant
public void run() {
prepare("action1");
execute("action1");
release("action1");
}
// Compliant
private static final String ACTION_1 = "action1";
public void run() {
prepare(ACTION_1);
execute(ACTION_1);
release(ACTION_1);
}
3.Try-with-resources should be used -优先使用Try-with-resources
try-with-resource并不是JVM虚拟机的新增功能,只是JDK实现了一个语法糖,当你将上面代码反编译后会发现,其实对JVM虚拟机而言,它依然是之前try/catch/finally的写法
// Noncompliant
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(fileName);
br = new BufferedReader(fr);
return br.readLine();
} catch (...) {
} finally {
if (br != null) {
try {
br.close();
} catch(IOException e){...}
}
if (fr != null ) {
try {
br.close();
} catch(IOException e){...}
}
}
// Compliant
try (
FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr)
) {
return br.readLine();
}
catch (...) {}
4.Jump statements should not occur in "finally" blocks -跳出语句不应该在finally里面
在finally代码块里return、break、throw等操作,会抑制try或catch块中抛出的任何未处理的异常传播。
// Noncompliant
public static void doSomethingWhichThrowsException() {
try {
throw new RuntimeException();
} finally {
doSomething()
/* ... */
return;
}
}
// Compliant
public static void doSomethingWhichThrowsException() {
try {
throw new RuntimeException();
} finally {
doSomething()
/* ... */
}
}
or
public void upload(File file) throws IOException {
ChannelSftp c = (ChannelSftp) channel;
BufferedInputStream bis = new BufferedInputStream(file.toInputStream());
SftpException sftpException = null;
try {
String uploadLocation = Files.simplifyPath(this.fileLocation +"/" + file.getName());
c.put(bis, uploadLocation);
} catch (SftpException e) {
sftpException = e;
throw new IllegalTargetException("Error occurred while uploading" + e.getMessage());
} finally {
if (sftpException != null) {
try {
bis.close();
} catch (Throwable t) {
sftpException.addSuppressed(t);
}
} else {
bis.close();
}
}
}
5.Constant names should comply with a naming convention -常量类型命名不符合规则
^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$
// Noncompliant
public class MyClass {
public static final int first = 1;
}
public enum MyEnum {
first;
}
// Compliant
public class MyClass {
public static final int FIRST = 1;
}
public enum MyEnum {
FIRST;
}
6.Methods should not be empty -方法不能为空
// Noncompliant
public void doSomething() {
}
// Compliant
public void doSomething() {
// Do nothing because of X and Y.
//or
throw new UnsupportedOperationException();
}
7."String#replace" should be preferred to "String#replaceAll" -优先使用replace
replace和replaceAll效果是一样的,只不过replaceAll是正则表达式替换,效率低
8."switch" statements should have "default" clauses -switch语句要有default字句
// Compliant
public void doSomething() {
switch (type) {
case "0":
return ItemTypeEnum.YZJ;
default:
// Do nothing because of X and Y.
//or
return null;
}
}
9."@RequestMapping" methods should specify HTTP method -@RequestMapping该注解要指定HTTP方法
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
可以简化为
@GetMapping("/get/{id}")
10.Factory method injection should be used in "@Configuration" classes -不要对有@Configuration注解的配置类进行Field级的依赖注入
在@Configuration构造的时候,需要加载依赖,但是@Configuration下面的@Bean初始化时并不是都会用到这些依赖,增加了依赖循环的风险
所以在@Bean初始化的时候用哪个依赖,去加载哪个
// Noncompliant
@Configuration
public class FooConfiguration {
@Autowired
private DataSource dataSource;
@Bean
public MyService myService() {
return new MyService(this.dataSource);
}
@Bean
public MyService myService() {
return new MyService(dataSource);
}
}
// Compliant
@Configuration
public class FooConfiguration {
@Bean
public MyService myService(DataSource dataSource) {
return new MyService(dataSource);
}
@Bean
public MyService myService() {
return new MyService(dataSource);
}
}
11."static" base class members should not be accessed via derived types -不要使用子类的名称访问父类的静态成员,容易造成混淆
// Noncompliant
public class JsonTest {
public void test() {
String results = "test";
Test str = JSONObject.parseObject(results, Test.class);
}
}
// Compliant
public class JsonTest {
public void test() {
String results = "test";
Test str = JSON.parseObject(results, Test.class);
}
}