SonarLint是一个IDE插件,可帮助开发人员在编写代码时检测和修复质量问题。就像拼写检查器一样,SonarLint也会在提交代码之前对错误进行修正。开发人员可以直接从IDE市场获得它,然后它将在编码时(Java、JavaScript、PHP、Python和HTML)检测新的bug和质量问题。## 严重程度
打开IDEA官方插件网站:
http://plugins.jetbrains.com/idea
搜索想要安装的插件,比如本文要安装的插件 SonarLint,在下面提示的下拉备选中,选择SonarLint跳转到插件页面.
在插件页面下面找到历史版本(Version History),找到想使用的版本,点击downLoad等待下载完成.
插件安装成功以后,打开插件配置界面,路径:File–Setting-Tools-SonarLint
弹窗窗口里,填写这个SonarLint的名称,我们使用的是本地sonarQube,选择的右边配置,输入sonarQube
IP和端口号.完成后点击Next.
在需要扫描的文件或者文件夹右击->SonarLint->Analyze with SonarLint
Current file:当前文件(展示当前文件存在的哪些问题,以及解决方法)
Rule:规则(告诉你问题的具体内容,并在最后告诉你如何解决这个问题)
Report:报告(鼠标移动到项目根目录,右键选择Ayalyze,选择Ayalyze with SonarLint,完成之后的结果显示,包含整个项目的所有文件的问题)
Locations:位置(告诉你,在哪个地方有问题,问题的重复位置)
Issues:问题 每个issue有五种等级
BLOCKER(致命):会影响应用程序的缺陷:内存泄漏,未关闭的JDBC连接…必须立刻修复的代码;
CRITICAL(关键):可能会影响应用程序的缺陷或者是安全性缺陷:空的catch块,sql注入,…必须立刻查看代码;
MAJOR(主要):可能会影响开发者效率的质量缺陷:未覆盖的代码,重复块,未使用的参数….
MINOR(微小):可能会影响开发者效率的质量缺陷:每行不能太长,“switch”语句应该至少有三个条件….
INFO(未知):既不是缺陷也不是质量问题,只是一个发现。
每个issue有三个状态
字符串文字不应该重复
代码中多次出现同一个字符串
应该将重复字符串抽取为常量
public static final String
弃用的元素应该同时具有注释和Javadoc标记
永远不应该抛出泛型异常
通用异常不应抛出 例如 Error Exception Throwable RuntimeException,修改为具体的或者自定义异常
在处理异常时,如果不往上抛的话,可以使用@SneakyThrows (编译后生成try catch)在本层处理。
方法名应该遵循命名约定
方法应该按照规范命名
字段名应该遵循命名约定
字段名应该遵循命名约定
应该删除不必要的引用
应该删除不必要的引用
快捷键 ctrl + alt + o
应该删除不必要的引用
应该删除不必要的引用
快捷键 ctrl + alt + o
不应该使用原始类型
方法的返回值类型,参数的类型 应该明确 不应该使用泛型
不应该使用同步类Vector, Hashtable, Stack和StringBuffer
使用这些同步类虽然是线程安全的,但是比较影响性能
“StandardCharsets”常量应该是首选
使用StandardCharsets.UTF_8 静态变量类型为charset 代替了HttpConstant.REQUEST_ENCODING这种静态变量类型为string的 符合java8规范
不应该使用同步类Vector, Hashtable, Stack和StringBuffer
使用这些同步类虽然是线程安全的,但是比较影响性能
不应该使用同步类Vector, Hashtable, Stack和StringBuffer
使用这些同步类虽然是线程安全的,但是比较影响性能
局部变量不应该声明后立即返回或抛出
本地变量如果赋值之后直接return了,那就直接return本地变量的赋值语句。
实用程序类不应该有公共构造函数
公用类的工具类不应该有公共的构造函数,公用的工具类是静态成员的集合,并不意味这要实例化,当工具类不定义构造函数,Java会自动向不定义构造函数的每个类添加公共的构造函数,和公用类不应该具有公共的构造函数冲突了,因此我们需要手动添加该公用工具类的构造函数。
/**
* @Classname AdentUtil
* @Description 中介工具类
* @Version 1.0.0
* @Date 2023/3/27 13:46
* @Created by admin
*/
public class AdentDataTransferUtil {
/**
* 构造下载报文
* @param adentResultFileGeneralRespDto
* @return
*/
public static UniteAdentResultFileRespDto getUniteAdentResultFileRespDto(AdentResultFileGeneralRespDto adentResultFileGeneralRespDto) {
UniteAdentResultFileRespDto uniteAdentResultFileRespDto=null;
if (adentResultFileGeneralRespDto != null) {
uniteAdentResultFileRespDto=new UniteAdentResultFileRespDto();
uniteAdentResultFileRespDto.setFileUnid(adentResultFileGeneralRespDto.getUnid());
uniteAdentResultFileRespDto.setFileName(adentResultFileGeneralRespDto.getName());
uniteAdentResultFileRespDto.setDownlaodUrl(adentResultFileGeneralRespDto.getDownloadUrl());
}
return uniteAdentResultFileRespDto;
}
private AdentDataTransferUtil() {
throw new IllegalStateException("Utility class");
}
}
方法不应该有太多参数
用Spring的@RequestMapping(以及相关的快捷注释,如@GetRequest)或@JsonCreator注释的方法可能有很多参数,封装是可能的。因此,这些方法将被忽略。
嵌套的代码块不应该留空
删除嵌套的空的代码块
修饰符应该以正确的顺序声明
不应该使用“@Deprecated”代码
不能使用 或者不建议使用 @Deprecated 修饰的代码
例:import org.springframework.util.StringUtils; 引入了spring的包,但是它的StringUtils。isEmpty()不被建议使用,改用其他的的包 比如 org.apache.commons.lang3.StringUtils
跟踪“TODO”标签的使用
将与该对象进行相等比较的对象
if(entry.getCode()==condition){}
修改为if(entry.getCode() != null && entry.equals(condition)){}
不应该在同一行上声明多个变量
“enum”字段不应该是公共可变的
修改访问修饰符
“静态”基类成员不应该通过派生类型访问
原代码:JSONArray licenseArr = JSONArray.parseArray(licenseData);
修改后 JSONArray licenseArr = JSON.parseArray(licenseData);
为了代码清晰起见,永远不要使用子类的名称访问父类的静态成员。这样做会造成混淆,并且可能会导致存在两个不同的静态成员的错觉。直接使用父类访问父类静态成员。
应该使用菱形操作符(“<>”)
Java 7引入了diamond操作符(<>)来减少泛型代码的冗长。例如,不必在列表的声明和构造函数中声明列表的类型,现在可以使用<>简化构造函数声明,编译器将推断类型
应该使用Collection.isEmpty()来测试是否为空
“switch”语句应该至少有3个“case”子句
如果不够三个case字句,改为用if,else
可折叠的“if”语句应该合并
Noncompliant Code Example
if (file != null) {
if (file.isFile() || file.isDirectory()) {
/* ... */
}
}
Compliant Solution
if (file != null && isFileOrDirectory(file)) {
/* ... */
}
private static boolean isFileOrDirectory(File file) {
return file.isFile() || file.isDirectory();
}
未使用的作业应该被删除
当局部变量被赋值后,后续指令不会读取该值时,就会发生死存储。计算或检索一个值,然后重写或丢弃它,可能表明代码中存在严重错误。即使这不是一个错误,它最多也是一种资源浪费。因此,应使用所有计算值。
“Serializable”类中的字段应该是瞬态的或者是可序列化的
当一个类实现了序列化接口 Serializable,意味着他可以可以序列化和反序列,当这个类里面的属性B没有实现 序列化接口 Serializable,意味着B不能序列化和反序列化,那么也就是类中的属性B不能序列化,sonar会报错。
1.为这个类B实现序列化接口 implement serializable
2.在属性B前面加上 transient 关键字 — private transient B b;
transient 对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。
“String#replace"应该优先于"String#replaceAll”
简单替换逻辑使用replace效能更高
方法不应该为空
使填写方法注释或者私有化构造器
private Assert() {
throw new IllegalStateException("Assert class");
}
应该删除未使用的“私有”方法
标准输出不应该直接用于记录任何内容
应该返回空数组和集合,而不是null
Noncompliant Code Example
public static List<Result> getAllResults() {
return null; // Noncompliant
}
public static Result[] getResults() {
return null; // Noncompliant
}
public static Map<String, Object> getValues() {
return null; // Noncompliant
}
public static void main(String[] args) {
Result[] results = getResults();
if (results != null) { // Nullity test required to prevent NPE
for (Result result: results) {
/* ... */
}
}
List<Result> allResults = getAllResults();
if (allResults != null) { // Nullity test required to prevent NPE
for (Result result: allResults) {
/* ... */
}
}
Map<String, Object> values = getValues();
if (values != null) { // Nullity test required to prevent NPE
values.forEach((k, v) -> doSomething(k, v));
}
}
Compliant Solution
public static List<Result> getAllResults() {
return Collections.emptyList(); // Compliant
}
public static Result[] getResults() {
return new Result[0]; // Compliant
}
public static Map<String, Object> getValues() {
return Collections.emptyMap(); // Compliant
}
public static void main(String[] args) {
for (Result result: getAllResults()) {
/* ... */
}
for (Result result: getResults()) {
/* ... */
}
getValues().forEach((k, v) -> doSomething(k, v));
}
标准输出不应该直接用于记录任何内容
空指针不应该被解引用
对该对象加非空判断 例如:Objects.requireNonNull(obj);
包声明应该与源文件目录匹配
删除所在的包引用,自动重新set包路径
应该返回空数组和集合,而不是null
返回一个new 对象就好了 或者参照示例
public static List<Result> getAllResults() {
return Collections.emptyList(); // Compliant
}
public static Result[] getResults() {
return new Result[0]; // Compliant
}
public static Map<String, Object> getValues() {
return Collections.emptyMap(); // Compliant
}
public static void main(String[] args) {
for (Result result: getAllResults()) {
/* ... */
}
for (Result result: getResults()) {
/* ... */
}
getValues().forEach((k, v) -> doSomething(k, v));
}
“@Override”应该用于重写和实现方法
需要为被提示的方法加上@Override
方法的认知复杂性不应太高
需要优化代码
XML解析器不应该容易受到XXE攻击