测试作业2-代码静态分析

测试作业2-代码静态分析

参考:(77条消息) Intellij IDEA 使用checkstyle、pmd、findbugs检查静态代码质量_码农-文若书生的博客-CSDN博客_idea pmd

FindBugs参考:[(77条消息) IDEA插件系列(3):FindBugs插件检查项目bug_二木成林的博客-CSDN博客](https://blog.csdn.net/cnds123321/article/details/102852177#:~:text=提供静态字节代码分析,以从IntelliJ,IDEA中查找Java代码中的错误。 FindBugs是Java的缺陷检测工具,它使用静态分析来查找200多种错误模式,例如空指针取消引用,无限递归循环,对Java库)

check使用参考:[(77条消息) IDEA下安装与使用CheckStyle_杨林伟的博客-CSDN博客_checkstyle idea](https://blog.csdn.net/qq_20042935/article/details/112602107#:~:text=IDEA下安装与使用CheckStyle 1 1. 前言 CheckStyle 是 SourceForge 下的一个项目,提供了一个帮助JAVA开发人员遵守某些编码规范的工具。,3. 配置CheckStyle 3.1 新建CheckStyle代码规范文件 首先在本地新建 checkstyle.xml 文件,里面的内容如下: )

分析源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Example{
int a;
int ans;

public Example(int m, int n) {
a=m;
b=n;
}

public int Function_A(int x, int y) {
if (x<6 &y>0) {
ans=x+a;
} else {
ans=x-a;
}
return ans;
}

public int Function_B(intx) {
if (x<6)
ans=x*a;
else ans=x/b;
}
}

PMD静态分析

PMD工具下载:

1、首先在IDEA的setting中找到plugin

image-20221128181742853

2、之后搜索PMD插件并下载:

image-20221128181840287

3、之后指定待分析的代码并鼠标右键选择run PMD:

image-20221128181440031

4、最后得到分析结果:

  1. image-20221128182440601

    代码第1行的publicclass出现拼写错误。

  2. image-20221128182610904

    代码第19行出现变量定义错误:intx。

  3. 将以上两个结果修改正确之后,再次run PMD并将结果保存为网页:

    image-20221128211726932

Checkstyle静态分析

Checkstyle工具下载:

1、同样下载Checkstyle工具插件:

image-20221128182117062

2、添加自定义规则:

image-20221128220103772

3、检测代码得到如下结果:

image-20221128215320720

此外,在使用Checkstyle静态分析时,出现了The source file could not be parsed by Checkstyle的问题,经过网上查阅资料和试错,发现将Checkstyle的version改为8.1版本之下即可。

总结

综上结果,对比两种工具:

工具 目的 检查项
PMD 检查java源文件中的潜在问题 空try/catch/finally/switch语句块、未使用的局部变量、参数和private方法、空if/while语句、过于复杂的表达式、复杂类
Checkstyle 检查java源文件是否与代码规范相符 java注释、命名规范、多余的imports、size度量、缺少必要的空格、重复代码

附录

checkstyle.xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<!-- 官方主页:https://checkstyle.sourceforge.io -->
<!-- 检查文件是否以一个空行结束 -->
<module name="NewlineAtEndOfFile"/>
<!-- 文件长度不超过1500行 -->
<module name="FileLength">
<property name="max" value="1500"/>
</module>
<!-- 每行不超过120个字 -->
<module name="LineLength">
<property name="max" value="150"/>
</module>

<module name="TreeWalker">
<!-- 想严格对文件头进行检查,请把文件头定义在一个外部文件中,如:java_header_file.txt 然后使 用"headerFile"属性:
<module name="Header">
<property name="headerFile" value="java_header_file.txt"/>
<property name="ignoreLines" value="1, 5"/>
</module>
-->

<!-- 忽略掉文件头的几行声明 不指定外部文件时出错,暂不使用
<module name="Header">
<property name="ignoreLines" value="1, 5"/>
</module>
-->

<!-- ********************************javadoc的检查********************-->
<!-- 检查Javadoc -->
<module name="JavadocStyle">
<!-- 忽略句号结尾检查 -->
<property name='checkFirstSentence' value='false'/>
<property name='checkEmptyJavadoc' value='true'/>
</module>
<!-- 检查所有的interface和class的doc -->
<module name="JavadocType">
<!-- 注释里允许所有注解 -->
<property name='allowUnknownTags' value='true'/>
</module>
<!-- 检查所有方法的javadoc 注意方法上的@param XXX后必须跟参数说明检查才能通过 -->
<module name='MissingJavadocMethod'>
<property name="allowMissingPropertyJavadoc" value="true"/>
<property name="allowedAnnotations" value="Override,Deprecated,ApiOperation"/>
<property name="ignoreMethodNamesRegex" value="main"/>
</module>
<module name="JavadocMethod"/>
<!-- 变量的javadoc -->
<module name="JavadocVariable">
<!-- 忽略检查的变量名 -->
<property name='ignoreNamePattern' value='.*Business|.*Service|.*Handler|.*Mapper|.*Template|.*Client|.*Util.*|LOG|LOGGER'/>
</module>

<!-- ********************************import方面的检查*********** -->
<!-- import中避免星号"*" -->
<module name="AvoidStarImport"/>
<!-- 检查是否从非法的包中导入了类 -->
<module name="IllegalImport"/>
<!-- 检查是否导入了多余的包 -->
<module name="RedundantImport"/>
<!--没用的import检查,比如:1.没有被用到 2.重复的 3.import java.lang的 4.import与该类在同一个package的-->
<module name="UnusedImports"/>

<!-- ********************************命名规则检查****************** -->
<!-- 包名检查 ^[a-z]+(\.[a-z][a-z0-9]*)*$ -->
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern" value="包名 ''{0}'' 要符合 ''{1}''格式."/>
</module>
<!-- 类型(Class或Interface)名 ^[A-Z][a-zA-Z0-9]*$-->
<module name="TypeName">
<property name="severity" value="warning"/>
<message key="name.invalidPattern" value="名称 ''{0}'' 要符合 ''{1}''格式."/>
</module>
<!-- 方法名 ^[a-z][a-zA-Z0-9]*$-->
<module name="MethodName"/>
<!-- 方法的参数命名 ^[a-z][a-zA-Z0-9]*$-->
<module name="ParameterName "/>
<!-- 非static型变量 ^[a-z][a-zA-Z0-9]*$-->
<module name="MemberName"/>
<!-- 常量(static , final 字段) ^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$-->
<module name="ConstantName"/>
<!-- 局部的final变量,包括catch中的参数 ^[a-z][a-zA-Z0-9]*$ -->
<module name="LocalFinalVariableName"/>
<!-- 局部的非final型的变量,包括catch中的参数 ^[a-z][a-zA-Z0-9]*$ -->
<module name="LocalVariableName"/>
<!-- 仅仅是static型的变量(不包括staticfinal型) ^[a-z][a-zA-Z0-9]*$ -->
<module name="StaticVariableName"/>

<!-- **************方法的参数个数不超过5个。 并且不对构造方法和重写方法进行检查*******-->
<module name="ParameterNumber">
<property name="tokens" value="METHOD_DEF"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="max" value="5"/>
</module>

<!-- ************************代码行数及行代码长度限制****************** -->
<!-- 文件长度不超过1500行,放在TreeWalker前面 -->
<!-- 方法不超过300行 -->
<module name="MethodLength">
<property name="tokens" value="METHOD_DEF"/>
<property name="max" value="300"/>
</module>
<!-- 每行不超过120个字
<module name="LineLength">
<property name="max" value="150"/>
</module>
-->
<!-- ****************************空格限定***************************** -->
<!-- 检查约定方法名与左边圆括号之间不许出现空格
public void wrongStyleMethod (){
public void wrongStyleMethod
(String para1, String para2){
都是不能通过的,只允许方法名后紧跟左边圆括号"("-->
<module name="MethodParamPad"/>

<!-- 不允许左圆括号右边有空格,也不允许与右圆括号左边有空格
public void wrongStyleMethod( String para1, String para2 ){
public void correctStyleMethod(String para1, String para2){
都不能通过-->
<module name="ParenPad"/>

<!-- 在类型转换时,不允许左圆括号右边有空格,也不允许与右圆括号左边有空格
Object myObject = ( Object )other;
不能通过-->
<module name="TypecastParenPad"/>

<!-- 代码中不允许使用"tab"键。('\t') 因为在不同的编辑器下有的tab占8个空格(如windows记事
本),有的占4个(如当前大多数IDE)。
<module name="TabCharacter"/>
-->
<!-- 检查在某个特定关键字之后应保留空格 -->
<module name="NoWhitespaceAfter"/>
<!-- 检查在某个特定关键字之前应保留空格 -->
<module name="NoWhitespaceBefore"/>
<!-- 操作符换行策略检查 -->
<module name="OperatorWrap"/>
<!-- 检查分隔符是否在空白之后 -->
<module name="WhitespaceAfter"/>
<!-- 检查分隔符周围是否有空白 -->
<module name="WhitespaceAround"/>


<!-- **********************关键字********************************** -->
<!-- 每个关键字都有正确的出现顺序。比如 public static final XXX 是对一个常量的声明。如果使用
static public final 就是错误的 -->
<module name="ModifierOrder"/>
<!-- 过滤多于的关键字-->
<module name="RedundantModifier"/>


<!-- ***********************空白域************************************* -->
<!-- 不能出现空白区域 -->
<module name="EmptyBlock"/>
<!-- 所有区域都要使用大括号 if(true)System.out.println("if 嵌套浓度限定");不能通过-->
<module name="NeedBraces"/>
<!-- 多余的括号 -->
<module name="AvoidNestedBlocks">
<property name="allowInSwitchCase" value="true"/>
</module>
<!-- 检查左大括号位置 -->
<module name="LeftCurly"/>
<!-- 检查右大括号位置 -->
<module name="RightCurly"/>

<!-- ******************************编码方面的检查 **********************-->
<!-- 检查空的代码段
不许出现空语句
int a = 0; //正常
; // 这里就是一个空的语句
int b = 0; //正常
-->
<module name="EmptyStatement"/>
<!-- 如果某个变量一直都没变,那么它就应该是final型的
<module name="FinalLocalVariable"/>
-->
<!-- 检查在重写了equals方法后是否重写了hashCode方法 -->
<module name="EqualsHashCode"/>
<!-- 不允许使用switch语句
<module name="IllegalToken">
<property name="tokens" value="LITERAL_SWITCH"/>
</module>
-->
<!-- 检查switch语句是否有default -->
<module name="MissingSwitchDefault"/>
<!-- 检查局部变量或参数是否隐藏了类中的变量 -->
<module name="HiddenField">
<property name="tokens" value="VARIABLE_DEF"/>
</module>
<!-- 内部赋值语句 :String s = Integer.toString(i = 2); -->
<module name="InnerAssignment"/>
<!-- 绝对不能容忍魔法数 ,即数据标识常量化
<module name="MagicNumber"/>
-->
<!-- 循环控制变量不能被修改
for (int i = 0; i < 1; i++) {
i++; // 这里是极可能是程序员大意写出来的。
}
-->
<module name="ModifiedControlVariable"/>
<!-- 多余的throw
<module name="RedundantThrows"/>
-->
<!-- 未被简化的条件表达式 检查过度复杂的条件表达式,
比如: (b == true), b || true, !false, 难读且容易出错 -->
<module name="SimplifyBooleanExpression"/>
<!-- 未被简化的布尔返回值
if (valid()){
return false;
}else{
return true;
}
就可以写成:
return !valid();
-->
<module name="SimplifyBooleanReturn"/>
<!-- String的比较不能用!= 和 == -->
<module name="StringLiteralEquality"/>
<!-- 限制for循环最多嵌套2层 -->
<module name="NestedForDepth">
<property name="max" value="4"/>
</module>
<!-- if最多嵌套3层 -->
<module name="NestedIfDepth">
<property name="max" value="5"/>
</module>
<!-- try最多被嵌套2层 -->
<module name="NestedTryDepth">
<property name="max" value="5"/>
</module>
<!--重载方法是否在同个地方-->
<module name="OverloadMethodsDeclarationOrder"/>
<!-- 检查并确认一个类的clone()方法调用了父类的clone() -->
<module name="SuperClone"/>
<!-- 检查并确认一个类的finalize()调用了父类的finalize() -->
<module name="SuperFinalize"/>
<!-- 不能catch java.lang.Exception,异常分类处理
<module name="IllegalCatch">
<property name="illegalClassNames" value="java.lang.Exception"/>
</module>
-->
<!-- 确保一个类有package声明 -->
<module name="PackageDeclaration"/>
<!-- 一个方法中最多有10个return -->
<module name="ReturnCount">
<property name="max" value="10"/>
<property name="maxForVoid" value="10"/>
</module>
<!-- 确保某个class 在被使用时都已经被初始化成默认值(对象是null ,
数字和字符是0 , boolean 变量是false.)了 -->
<module name="ExplicitInitialization"/>
<!-- 不许有同样内容的String
<module name="MultipleStringLiterals"/>
-->
<!-- 同一行不能有多个声明 -->
<module name="MultipleVariableDeclarations"/>
<!-- 不必要的圆括号 检查不必要的圆括号”(,)”。比如, if(((((true))))) -->
<module name="UnnecessaryParentheses"/>
<!-- 限制一个布尔表达式中的 &&, || 和^的个数。可以让代码看起来更清晰,容易排错和维护 -->
<module name="BooleanExpressionComplexity">
<property name="max" value="8"/>
</module>
<!-- 一个类中如果使用太多其他的类,是肯定会增加系统复杂度的。使用其他的类越少,耦合度就越少 -->
<module name="ClassDataAbstractionCoupling">
<property name="max" value="50"/>
</module>
<!-- 确保函数的分支复杂度没有超出限制
<module name="CyclomaticComplexity">
<property name="max" value="20"/>
</module>
-->
<!-- NPATH 量度计算了一个函数的可执行的分支个数
<module name="NPathComplexity">
<property name="max" value="20"/>
</module>
-->

<!-- 类设计检查 -->
<!-- 检查只有private构造函数的类是否声明为final -->
<module name="FinalClass"/>
<!-- 检查接口是否仅定义类型
<module name="InterfaceIsType"/>
-->
<!-- 检查类成员的可见度 检查类成员的可见性。只有static final 成员是public的除非在本检查的protectedAllowed和packagedAllowed属性中进行了设置-->
<module name="VisibilityModifier">
<property name="packageAllowed" value="true"/>
<property name="protectedAllowed" value="true"/>
</module>

<!-- 禁止使用System.out.println -->
<module name="Regexp">
<property name="format" value=".printStackTrace"/>
<property name="illegalPattern" value="true"/>
</module>
<module name="Regexp">
<property name="format" value="System.out.println"/>
<property name="illegalPattern" value="true"/>
</module>

<!-- ************************其他*********************************** -->
<!-- 检查并确保所有的常量中的L都是大写的。因为小写的字母l跟数字1太象了 -->
<module name="UpperEll"/>
<!-- 检查数组类型的定义是String[] args,而不是String args[] -->
<module name="ArrayTypeStyle"/>
<!-- 不许使用与代码同行的注释
<module name="TrailingComment"/>
-->
<!-- 不许存在TO DO
<module name="TodoComment"/>
-->
<!-- 除了正常的程序入口之外,所有的main方法都应该被删掉或注释掉 -->
<module name="UncommentedMain">
<property name="excludedClasses" value=".*[Application,Test]$"/>
</module>
<!-- 检查并确保所有的常量中的L都是大写的。也就是在常量中没有使用”l”而是用的”L”,比如long型常
量,都要以”L”结尾。这与Sun编码规范 3.10.1 相一致。小写的字母l 跟数字1 太象了 -->
<module name="UpperEll"/>
</module>
</module>

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2023-2024 Guijie Wang
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信