Code Review
制度Continuous Code Quality
)分析工具,包括静态分析和动态分析;20
多种语言;bug
、安全隐患(vulnerability
)、不规范代码(Code Smells
);Quality Gate
)及Quality Profile
;SonarQube 使用手册 https://guide.daocloud.io/dcs25/sonarqube-22385147.html
SonarQube
质量规则页面SonarLint
是一个免费的开源IDE
扩展,可识别并帮助您在编写代码时解决质量和安全问题。像拼写检查器一样,SonarLint
会显示缺陷并提供实时反馈和清晰的修复指导,以便从一开始就提供干净的代码。Idea SonarLint
插件使用Idea
使用 插件如下官方检测规则及修复示例:https://jira.sonarsource.com/browse/RSPEC-2637?jql=project%20%3D%20RSPEC%20AND%20resolution%20%3D%20Unresolved%20ORDER%20BY%20updated%20DESC
翻译:将连接字符串传递给日志记录方法也可能导致不必要的性能损失,因为每次调用该方法时都会执行连接,无论日志级别是否低到足以显示消息。应该使用内置的字符串格式而不是字符串连接,如果消息是方法调用的结果,则应该完全跳过前置条件,而应该有条件地抛出相关异常。
反例
String message = "Hellow World!";
logger.info("Test Info message:"+message);
String message = "Hellow World!";
String format = String.format("Test Info message:%s", message);
logger.info(format);
System.out.printf("Hellow");
private static final Logger logger = Logger.getLogger(String.valueOf(Demo.class));
logger.info("Hellow");
logger.info(String.valueOf((char)c));
String s2 = String.valueOf((char) c);
logger.info(s2);
Exception
等。throw new Exception("Test");
public class MyException extends RuntimeException{
public MyException() {
}
public MyException(String message) {
super(message);
}
}
throw new MyException("Hellow");
String message = "Hellow Test!";
logger.info(String.format("method error: {}",message));
String message = "Hellow Test!";
logger.info(String.format("method error: %s",message));
interruptedexception
,在这种情况下,简单地将异常计数记录为“忽略”。InterruptedException
的抛出将清除线程的中断状态,因此,如果异常没有得到正确的处理,那么线程被中断的事实就会丢失。相反,interruptedexception
应该被重新抛出——立即或在清除方法的状态之后——或者应该通过调用thread .interrupt()
重新中断线程,即使这是一个单线程的应用程序。任何其他操作都有延迟线程关闭的风险,并丢失线程被中断的信息——可能没有完成其任务。private void dealAddNum() {
try {
num++;
Thread.sleep(100);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
}
private void dealAddNum() {
try {
num++;
Thread.sleep(100);
} catch (InterruptedException e) {
log.info(e.getMessage());
Thread.currentThread().interrupt();
}
}
翻译:方法没有方法主体有以下几个原因:这是一个无意的疏忽,应该加以修正,以防止生产中出现意外的行为。它还没有得到支持,或者永远不会得到支持。在这种情况下,应该抛出UnsupportedOperationException
。该方法是一个故意为空的覆盖。在这种情况下,一个嵌套的注释应该解释空白覆盖的原因。
反例:
@Override
public void setProperties(Properties properties) {
}
@Override
public void setProperties(Properties properties) {
throw new UnsupportedOperationException();
}
ThreadLocal
变量就会被垃圾收集。在重用持有的线程时(在使用线程池的应用服务器上就是这种情况)可能会发生内存泄漏。private static final ThreadLocal<SimpleDateFormat> DATETIME_FORMATTER = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
private static final ThreadLocal<SimpleDateFormat> DATETIME_FORMATTER = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public void test1(){
try{
// do something
}catch(Exception e){
// do something
}finally{
DATETIME_FORMATTER.remove();
}
}
try/catch
块严重影响了源代码的可读性,因为它使理解哪个块捕获哪个异常变得非常困难。@Test
public void test1(){
try {
try{
}catch (NullPointerException e){
logger.info(e.getMessage());
}
}catch (Exception e){
logger.info(e.getMessage());
}
}
@Test
public void test1(){
try {
logger.info("test messages!");
}catch (Exception e){
logger.info(e.getMessage());
}
}
catch
块,而不是捕获一般异常,然后对类型进行测试。try {
// do somethings
} catch (Exception e) {
if (e instanceof InvocationTargetException) {
logger.error(LogConstant.LOG_FAILURE_PREFIX + (((InvocationTargetException) e).getTargetException()).getMessage());
} else {
logger.error(LogConstant.LOG_FAILURE_PREFIX + e.getMessage());
}
return result;
}
try{
logger.info("test!");
}catch (NullPointerException nullPointerException){
logger.info(nullPointerException.getMessage());
}catch (IllegalArgumentException illegalArgumentException){
logger.info(illegalArgumentException.getMessage());
}
Random
的nextDouble
方法的输出乘以一个随机整数。使用nextt
方法代替。当随机的任何返回浮点值的方法的返回值被转换为整数时,该规则会引发一个问题。user.setGender(((int)(10 * Math.random())) % 2 );
Random random = new Random();
user.setGender(random.nextInt(10) % 2 );
可变字段不应该是public static
不合规
public interface MyInterface {
public static String [] strings; // Noncompliant
}
public class A {
public static String [] strings1 = {"first","second"}; // Noncompliant
public static String [] strings2 = {"first","second"}; // Noncompliant
public static List<String> strings3 = new ArrayList<>(); // Noncompliant
// ...
}
private static final String [] COLUMN_NAMES = new String[]{"date","customerNumber","customerName",
"account","emailAdress","mobilePhoneNumber","emailStatus"};
public static List<String> getColumnNames() {
return Collections.unmodifiableList(Arrays.asList(COLUMN_NAMES));
}
final
将阻止重新分配变量,但这样做不会影响数组内部状态的可变性。可以改变的类型如果非常有必要声明为 ‘public static’
可以通过上述 Collections.unmodifiableList
方式实现。代码示例:https://blog.csdn.net/qq_37248504/article/details/115266913