检查代码格式checkstyle

来源:互联网 发布:node req.query 编辑:程序博客网 时间:2024/04/20 01:48

1.安装及配置
使用checkstyle有两种方式,可以直接在集成环境idea或eclipse中下载需要的插件,也可以在maven项目的pom.xml文件中添加插件。
1>下载插件
eclipse 可以利用eclipse的help里面的Eclipse marketplace选择下载;
idea 打开Settings——Plugins——可以选择Browse repositories 或者选择install from disk安装即可。
2>添加配置
在项目中添加以下配置:

<plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-checkstyle-plugin</artifactId>    <version>2.10</version>    <configuration>        <configLocation>config/sun_checks.xml</configLocation>    </configuration>    <executions>        <execution>            <id>checkstyle</id>            <phase>validate</phase>            <goals>                <goal>check</goal>            </goals>            <configuration>                <failOnViolation>true</failOnViolation>            </configuration>        </execution>    </executions></plugin>

上述中使用默认的规则,maven-checkstyle-plugin内置了4种规范:
● config/sun_checks.xml
● config/maven_checks.xml
● config/turbine_checks.xml
● config/avalon_checks.xml
如果不想使用默认的规则,则可以选择添加自定义check规则文件,只需要在红色部分替换以下配置:
${basedir}/src/main/resources/google_check.xml
注:如果想要忽略一些检查规则,则可以建立单独的checkstyle-suppressions.xml来设置,在pom.xml文件中配置即可。
2.使用checkstyle
运行命令:
mvn checkstyle:help 查看checkstyle-plugin的帮助
mvn checkstyle:check 检查项目是否满足checkstyle的检查,如果不满足检查失败,通过 target/checkstyle-result.xml文件查看具体错误
mvn checkstyle:checkstyle 检查项目是否满足checkstyle的检查,如果不满足检查不会失败, 通过target/checkstyle-result.xml文件查看具体错误
mvn checkstyle:checkstyle-aggregate同mvn checkstyle:checkstyle
3.主要的一些错误及解决方案
以google的check标准对项目做了checkstyle分析,主要错误参见以下:

File does not end with a newline 解决方法:删掉报错的类,新建一个同名的类,把代码全部复制过去(忽略此项)
Missing package-info.java file(在对应的包下新建该文件即可,需注意该文件是特殊的java类文件,描述和记录本包信息,只能声明默认访问权限的类)
Missing a Javadoc comment 缺少javadoc注释
‘>’ is not followed by whitespace 别且有 ‘(’ is preceded with whitespace. 定义集合和枚举的时候的时候,最后一个 ‘>’ 后面要有空格,’(’ 前面不容许有空格
Line has trailing spaces 多余的空行 解决方法:删除该行
File contains tab characters (this is the first instance) 包含制表符 解决方法:制表符替换成4个空格 可以在设置中去掉use tab character选项
First sentence should end with a period 注释的第一行文字结束应该加上一个’.’
Parameter xxx should be final 参数属性应当为final
‘xxx’ hides a field 全局和局部的变量名字重复,get set 方法中会写成类似这种:this.value=value(该项目中忽略)
Redundant ‘public’ modifier 多余的修饰符
在以下部分检查是否有多余的修饰符:
1> 接口和注解的定义;
2>final类的方法的final修饰符;
3>被声明为static的内部接口声明。
‘{’ is not preceded with whitespace 大括号后面必须空一格
‘=’ is not preceded with whitespace(或’=’ is not followed by whitespace) = 后面必须空一格
Variable ‘xxx’ must be private and have accessor methods.变量要改成private然后提供访问的方法 解决方法:给这些变量的修饰符改成private,然后提供set,get方法,并加上对应的方法javadoc注释、参数注释。并在返回值和参数类型前添加final。并把调用了这个变量的地方改成通过方法访问
Expected @throws tag for ‘Exception’ 在注释中希望有@throws的说明
Expected an @return tag 希望有预期的return标签
Method ‘xxx’ is not designed for extension - needs to be abstract, final or empty. 不是拓展或继承的方法,必须指定abstract,final或空
Wrong order for import 引入包的顺序错误 检查导入包的顺序或分组(字典序排序,静态最后)
Unknown tag @createdAt 不能识别的@注解
Name ‘xxx’ must match pattern ^[a-z][a-zA-Z0-9]*$ 命名必须符合规范 该正则为静态变量的命名规范
Should be alone on a line 应该单独成一行
Fall through from previous branch of the switch statement switch中的case在没有break或return等情况下,必须有注释
‘}’ should be on the same line ‘}’ 应该与下条语句位于同一行 解决方法:把’}’放到下一行的前面
All TODOs should be named. e.g. "TODO(johndoe): Refactor when v2 is released." todo规范相关
modifier out of order with the JLS suggestions static应该放在final前边
Utility classes should not have a public or default constructor 接口中的内部类中不应该有公共的或者默认的构造方法
Using the ‘.’ form of import should be avoided 引入包的时候不允许使用’.’

4.checkstyle检查项

具体checkstyle的检查项如下:(文档来源: http://blog.csdn.net/yang1982_0907/article/details/18086693)

1> Annotations(注解:5个)
Annotation Use Style(注解使用风格)
这项检查可以控制要使用的注解的样式。
Missing Deprecated(缺少deprecad)
检查java.lang.Deprecated注解或@deprecated的Javadoc标记是否同时存在。
Missing Override(缺少override)
当出现{@inheritDoc}的Javadoc标签时,验证java.lang.Override注解是否出现。
Package Annotation(包注解)
这项检查可以确保所有包的注解都在package-info.java文件中。
Suppress Warnings(抑制警告)
这项检查允许你指定不允许SuppressWarnings抑制哪些警告信息。你还可以指定一个TokenTypes列表,其中包含了所有不能被抑制的警告信息。

2> Javadoc Comments(Javadoc注释:6个)
Package Javadoc(包注释)
检查每个Java包是否都有Javadoc注释。
Method Javadoc(方法注释)
检查方法或构造器的Javadoc。
Style Javadoc(风格注释)
验证Javadoc注释,以便于确保它们的格式。可以检查以下注释:接口声明、类声明、方法声明、构造器声明、变量声明。
Type Javadoc(类型注释)
检查方法或构造器的Javadoc。默认不会检查author和version标记。
Variable Javadoc(变量注释)
检查变量是否具有Javadoc注释。
Write Tag(输出标记)
将Javadoc作为信息输出。可以作为样式表来使用,根据作者名排序报告。想要为一个标记定义格式,将tagFormat属性设置为相应的正则表达式即可。这项检查会使用两种不同的严重级别。当标记缺失时,使用标准的严重级别(Severity)。当标记存在时,使用附加的严重级别(tagSeverity)作为报告等级。

3> Naming Conventions(命名规约:12个)
Abstract Class Name(抽象类名称)
检查抽象类的名称是否遵守命名规约。
Class Type Parameter Name(类的类型参数名称)
检查类的类型参数名称是否遵守命名规约。
Constant Names(常量名称)
检查常量(用static final修饰的字段)的名称是否遵守命名规约。
Local Final Variable Names(局部final变量名称)
检查局部final变量的名称是否遵守命名规约。
Local Variable Names(局部变量名称)
检查局部变量的名称是否遵守命名规约。
Member Names(成员名称)
检查成员变量(非静态字段)的名称是否遵守命名规约。
Method Names(方法名称)
检查方法名称是否遵守命名规约。
Method Type Parameter Name(方法的类型参数名称)
检查方法的类型参数名称是否遵守命名规约。
Package Names(包名称)
检查包名称是否遵守命名规约。
Parameter Names(参数名称)
检查参数名称是否遵守命名规约。
Static Variable Names(静态变量名称)
检查静态变量(用static修饰,但没用final修饰的字段)的名称是否遵守命名规约。
Type Names(类型名称)
检查类的名称是否遵守命名规约。

下表为checkstyle的命名规范:
模块的”name”属性
检查范围
Format属性的默认值
AbstractClassName
抽象类
^Abstract.*|.Factory
ConstantName
常量(static , final 字段)
^[A-Z][A-Z0-9](_[A-Z0-9]+) LocalFinalVariableNamefinalcatch[az][azAZ09]
LocalVariableName
局部的非final型的变量, 包括catch的参数
^[a-z][a-zA-Z0-9]*MemberNamestatic[az][azAZ09]
MethodName
方法名
^[a-z][a-zA-Z0-9]*$
PackageName
Package名
^[a-z]+(.[a-zA-Z_][a-zA-Z0-9 _])ParameterName[az][azAZ09]
StaticVariableName
仅仅是static型的变量(不包括static final型)
^[a-z][a-zA-Z0-9]*TypeName(ClassInterface)[AZ][azAZ09]

4> Headers(文件头:2个)
Header(文件头)
检查源码文件是否开始于一个指定的文件头。headerFile属性可以指定一个文件,该文件包含了需要的文件头。还有另一种方法,文件头的内容可以直接在header属性中设置,而不使用外部文件。
Regular Expression Header(正则表达式文件头)
检查Java源码文件头部的每行是否匹配指定的正则表达式。

5> Imports(导入:7个)
Avoid Star (Demand) Imports(避免通配符导入)
检查没有import语句使用*符号。
解释:从一个包中导入所有的类会导致包之间的紧耦合,当一个新版本的库引入了命名冲突时,这样就有可能导致问题发生。
Avoid Static Imports(避免静态导入)
检查没有静态导入语句。
解释:导入静态成员可能会导致类成员之间的命名冲突。导入静态成员可能会导致代码的可读性很差,因为读者可能会搞不清楚成员到底位于哪个类中。
Illegal Imports(非法导入)
检查是否导入了指定的非法包。
Import Order Check(导入顺序检查)
检查导入包的顺序/分组。确保导入包的分组按照指定的顺序排列(例如,java.排在首位,javax.排在第二,以此类推),并且每个分组内导入的包都是按照字典序排列的。静态导入必须放在最后,并且也是按照字典序排列的。
Redundant Imports(多余导入)
检查是否存在多余的导入语句。如果一条导入语句满足以下条件,那么就是多余的:
1. 它是另一条导入语句的重复。也就是,一个类被导入了多次。
2. 从java.lang包中导入类,例如,导入java.lang.String。
3. 从当前包中导入类。
Unused Imports(未使用导入)
检查未使用的导入语句。
Import Control(导入控制)
控制允许导入每个包中的哪些类。
导入控制XML文档所使用的DTD文件位于
http://www.puppycrawl.com/dtds/import_control_1_0.dtd
它包含了上述XML文档的所有元素和属性。

6> Size Violations(尺寸超标:8个)
Anonymous inner classes lengths(匿名内部类长度)
检查匿名内部类的长度。
解释:如果一个匿名内部类变得非常长,那么就很难读懂它,并且难以跟踪方法的流程。因此,过长的匿名内部类通常应当被重构为一个具名内部类。可以参考Bloch编写的《Effective Java》的第93页。
Executable Statement Size(可执行语句数量)
将可执行语句的数量限制为一个指定的限值。
Maximum File Length(最大文件长度)
检查源码文件的长度。
解释:如果一个源码文件变得非常长,那么就会难以理解。因此,过长的类通常应当被重构成若干个较小的独立的类,每个类专注于一个特定的任务。
Maximum Line Length(最大行长度)
检查源码每行的长度。
Maximum Method Length(最大方法长度)
检查方法和构造器的长度。
Maximum Parameters(最大参数数量)
检查一个方法或构造器的参数的数量。
Outer Type Number(外层类型数量)
检查在一个文件的外层(或根层)中声明的类型的数量。
解释:一般认为给每个文件只定义一个外层类型是较好的做法。
Method Count(方法总数)
检查每个类型中声明的方法的数量。
它包括了每种可见范围方法的总数(private、package、protected、public)。

7> Whitespace(空格:12个)
Generic Whitespace(范型标记空格)
检查范型标记<和>的周围的空格是否遵守标准规约。这项规约是不可配置的。
Empty For Initializer Pad(空白for初始化语句填充符)
检查空的for循环初始化语句的填充符,也就是空格是否可以作为for循环初始化语句空位置的填充符。如果代码自动换行,则不会进行检查,正如以下代码所示:
for (
; i < j; i++, j–)
Empty For Iterator Pad(空白for迭代器填充符)
检查空的for循环迭代器的填充符,也就是空格是否可以作为for循环迭代器空位置的填充符。如果代码自动换行,则不会进行检查,正如以下代码所示:
for (Iterator foo = very.long.line.iterator();
foo.hasNext();
)
No Whitespace After(指定标记之后没有空格)
检查指定标记之后没有空格。若要禁用指定标记之后的换行符,将allowLineBreaks属性设为false即可。
No Whitespace Before(指定标记之前没有空格)
检查指定标记之前没有空格。若要允许指定标记之前的换行符,将allowLineBreaks属性设为true即可。
Operator Wrap(运算符换行)
检查代码自动换行时,运算符所处位置的策略。nl表示运算符必须在新行中,eol表示运算符必须在当前行的行末。
Method Parameter Pad(方法参数填充符)
检查方法定义、构造器定义、方法调用、构造器调用的标识符和参数列表的左圆括号之间的填充符。也就是,如果标识符和左圆括号位于同一行,那么就检查标识符之后是否需要紧跟一个空格。如果标识符和左圆括号不在同一行,那么就报错,除非将规则配置为允许使用换行符。想要在标识符之后使用换行符,将allowLineBreaks属性设置为true即可。
Paren Pad(圆括号填充符)
检查圆括号的填充符策略,也就是在左圆括号之后和右圆括号之前是否需要有一个空格。
Typecast Paren Pad(类型转换圆括号填充符)
检查类型转换的圆括号的填充符策略。也就是,在左圆括号之后和右圆括号之前是否需要有一个空格。
File Tab Character(文件制表符)
检查源码中没有制表符(’\t’)。
解释:
1. 为了能够更方便地阅读源码,开发者不应当在他们的文本编辑器中配置制表符的宽度。
2. 根据Apache Jakarta的编码标准:在一个分布式开发环境中,当提交的消息被发送到一个邮件列表中时,如果你使用了制表符,那么这些消息会变得几乎不可能阅读。
Whitespace After(指定标记之后有空格)
检查指定标记之后是否紧跟了空格。
Whitespace Around(指定标记周围有空格)
检查指定标记的周围是否有空格。
可以选择性地从检查策略中排除,通过设置allowEmptyMethods和allowEmptyConstructors属性即可。

8> Regexp(正则表达式:3个)
RegexpSingleline(正则表达式单行匹配)
检查单行是否匹配一条给定的正则表达式。可以处理任何文件类型。
解释:这项检查可以作为原型检查使用,能够发现常见的编码坏习惯,例如调用ex.printStacktrace()、System.out.println()、System.exit(),等等。
RegexpMultiline(正则表达式多行匹配)
检查多行是否匹配一条给定的正则表达式。可以处理任何文件类型。
解释:这项检查可以作为原型检查使用,能够发现常见的编码坏习惯,例如调用ex.printStacktrace()、System.out.println()、System.exit(),等等。
RegexpSingleLineJava(正则表达式单行Java匹配)
这项检查是RegexpSingleline的变种,用于检测Java文件中的单行是否匹配给定的正则表达式。它支持通过Java注释抑制匹配操作。

9> Modifiers(修饰符:2个)
Modifier Order(修饰符顺序)
检查代码中的标识符的顺序是否符合《Java Language Specification》中的第8.1.1、8.3.1章节所建议的顺序。正确的顺序应当如下:
1. public
2. protected
3. private
4. abstract
5. static
6. final
7. transient
8. volatile
9. synchronized
10. native
11. strictfp
Redundant Modifier(多余修饰符)
在以下部分检查是否有多余的修饰符:
1. 接口和注解的定义;
2. final类的方法的final修饰符;
3. 被声明为static的内部接口声明。

解释:《Java Language Specification》强烈不建议在接口定义中使用“public”和“abstract”来声明方法。
接口中的变量和注解默认就是public、static、final的,因此,这些修饰符也是多余的。
因为注解是接口的一种形式,所以它们的字段默认也是public、static、final的,正如它们的注解字段默认是public和abstract的。
定义为final的类是不能被继承的,因此,final类的方法的final修饰符也是多余的。

10> Blocks(代码块:5个)
Avoid Nested Blocks(避免嵌套代码块)
找到嵌套代码块,也就是在代码中无节制使用的代码块。
解释:内嵌代码块通常是调试过程的残留物,它们会使读者产生混淆。
Empty Block(空代码块)
检查空代码块。
Left Curly Brace Placement(左花括号位置)
检查代码块的左花括号的放置位置。
通过property选项指定验证策略。
若使用eol和nlow策略,则需要考虑maxLineLength属性。
Need Braces(需要花括号)
检查代码块周围是否有大括号,可以检查do、else、if、for、while等关键字所控制的代码块。
Right Curly Brace Placement(右花括号位置)
检查else、try、catch标记的代码块的右花括号的放置位置。
通过property选项指定验证策略。

11> Coding Problems(编码问题:43个)
Avoid Inline Conditionals(避免内联条件语句)
检测内联条件语句。内联条件语句的一个示例如下所示:
String a = getParameter(“a”);
String b = (a==null || a.length<1) ? null : a.substring(1);
解释:内联条件语句很难读懂,有些标准会禁止使用内联条件语句。
Covariant Equals(共变equals方法)
检查定义了共变equals()方法的类中是否同样覆盖了equals(java.lang.Object)方法。这项检查受到FindBugs的启发。
解释:错误地定义了一个共变equals()方法,而没有覆盖equals(java.lang.Object)方法,可能会产生不可预料的运行时行为。
Default Comes Last(默认分支置于最后)
检查switch语句中的default是否在所有的case分支之后。
解释:Java允许default位于switch语句中的任何地方。但是,如果default位于最后一个case分支之后,那么代码的可读性会更强。
Declaration Order Check(声明顺序检查)
根据Java编程语言的编码规约,一个类或接口的声明部分应当按照以下顺序出现:
1. 类(静态)变量。首先应当是public类变量,然后是protected类变量,然后是package类变量(没有访问标识符),最后是private类变量。
2. 实例变量。首先应当是public类变量,然后是protected类变量,然后是package类变量(没有访问标识符),最后是private类变量。
3. 构造器
4. 方法
Empty Statement(空语句)
检测代码中是否有空语句(也就是单独的;符号)。
Equals Avoid Null(避免调用空引用的equals方法)
检查equals()比较方法中,任意组合的String常量是否位于左边。
这项检查还会处理String.equalsIgnoreCase()调用(可以抑制这种警告)。

解释:调用String常量的equals()方法可以避免潜在的NullPointerException。同样,经常会发现在调用equals()方法之前,会进行空指针检查,不过在下面的示例中则没有必要这么做。
Equals and HashCode(equals方法和hashCode方法)
检查覆盖了equals()方法的类是否也覆盖了hashCode()方法。
解释:equals()方法和hashCode()方法约定,相等的对象必然具有相同的哈希码。因此,只要你覆盖了equals()方法,你就必须同时覆盖hashCode()方法,以确保可以在基于哈希的集合中使用你的类。
Explicit Initialization(显式初始化)
检查类或对象的成员是否显式地初始化为成员所属类型的默认值(对象引用的默认值为null,数值和字符类型的默认值为0,布尔类型的默认值为false)。
解释:每个实例变量都会被初始化两次,并且初始化为相同的值。在执行代码中指定的任何初始化操作之前,Java会初始化每个实例变量为它的默认值(0或null)。
Fall Through(跨越分支)
检查switch语句中是否存在跨越分支。如果一个case分支的代码中缺少break、return、throw或continue语句,那么就会导致跨越分支。
这项检查可以通过特殊的注释以抑制警告。默认情况下,在有跨越分支的case分支代码中添加“fallthru”、“fall through”、“fallthrough”、“falls through”、“fallsthrough”等注释(区分大小写)时,便可抑制警告。包含以上单词的注释必须在一行中,并且必须在当前case分支代码的最后一行中,或者与case语句在同一行。
Final Local Variable(final局部变量)
检查从未改变取值的局部变量是否被声明为final。这项检查还可以被配置为检查未修改过的参数是否被声明为final。
当配置为检查参数时,这项检查会忽略接口方法和抽象方法中的参数。
Hidden Field(隐藏字段)
检查局部变量或参数是否会遮蔽在相同类中定义的字段。
Illegal Instantiation(非法实例化)
检查是否有不合法的实例化操作,是否使用工厂方法更好。
解释:根据不同的项目,对于某些类来说,可能通过工厂方法来创建类实例更好,而不是调用类构造器。
一个简单的示例就是java.lang.Boolean类。为了节省内存和CPU周期,最好使用预定义的常量TRUE和FALSE。构造器的调用应当被替换为调用Boolean.valueOf()方法。
某些对性能有极端要求的项目可能需要其他的类也使用工厂方法,以便于提高缓存或对象池的使用效率。
Illegal Catch(非法异常捕捉)
从不允许捕捉java.lang.Exception、java.lang.Error、java.lang.RuntimeException的行为。
解释:缺乏经验的开发者经常会简单地捕捉Exception异常,试图处理多种异常类型。这会很不幸地使代码无意中捕捉到NullPointerException、OutOfMemoryErrors等系统异常。
Illegal Throws(非法异常抛出)
这项检查可以用来确保类型不能声明抛出指定的异常类型。从不允许声明抛出java.lang.Error或java.lang.RuntimeException。
Illegal Tokens(非法标记)
检查不合法的标记。
解释:某个语言特性经常会导致代码难以维护,或者开发新手难以理解。在某些框架中,其他特性可能不推荐使用,例如,在EJB组件中最好不要使用本地方法。
Illegal Tokens Text(非法标记文本)
检查是否有不合法的标记文本。
Illegal Type(非法类型)
检查代码中是否有在变量声明、返回值、参数中都没有作为类型使用过的特定类。包括一种格式检查功能,默认情况下不允许抽象类。
解释:帮助减少和实体类之间的耦合。另外,抽象类应当被认为是接口的一种简便的基类实现,因此不能是类型本身。
Inner Assignment(内部赋值)
检查子表达式中是否有赋值语句,例如String s = Integer.toString(i = 2);。
解释:这项检查会忽略for循环代码,其余所有的赋值操作都应当在它们自己的顶层语句中,以便于增强可读性。在上述的内部赋值代码中,很难看到变量是在哪儿赋值的。
JUnit Test Case(JUnit测试用例)
确保setUp()、tearDown()方法的名称正确,没有任何参数,返回类型为void,是public或protected的。
同样确保suite()方法的名称正确,没有参数,返回类型为junit.framewotk.Test,并且是public和static的。
解释:开发者时常会错误地命名这些方法,并且不会意识到这些方法没有被调用。
Magic Number(幻数)
检查代码中是否含有“幻数”,幻数就是没有被定义为常量的数值文字。默认情况下,-1、0、1、2不会被认为是幻数。
Missing Constructor(缺少构造器)
检查类(除了抽象类)是否定义了一个构造器,而不是依赖于默认构造器。
Missing Switch Default(缺少switch默认分支)
检查switch语句是否含有default子句。
解释:在每个switch语句中引入一条默认分支通常是一个很好的主意。即使开发者确信所有当前可能的分支都能覆盖到,这也应当在default分支中表达出来,例如,使用一条断言。这种方法使得代码可以应付以后的修改,例如,在一个枚举类型中引入新的类型。
Modified Control Variable(修改控制变量)
检查确保for循环的控制变量没有在for代码块中被修改。示例代码如下:
解释:如果在循环体中修改了控制变量,程序流程就会变得更加难以跟踪。可以用while循环替换for循环。
Multiple String Literals(多重字符串常量)
检查在单个文件中,相同的字符串常量是否出现了多次。
解释:重复代码会使得维护工作变得更加困难,因此最好用一个常量来替换多次出现。
Multiple Variable Declaration(多重变量声明)
检查每个变量是否使用一行一条语句进行声明。
解释:《SUN编码规约》的第6.1章节推荐应当使用一行一条语句声明一个变量。
Nested For Depth(for嵌套深度)
限制for循环的嵌套层数(默认值为1)。
Nested If Depth(if嵌套深度)
限制if-else代码块的嵌套层数(默认值为1)。
Nested Try Depth(try嵌套深度)
限制try代码块的嵌套层数(默认值为1)。
No Clone(没有clone方法)
检查是否覆盖了Object类中的clone()方法。
Package Declaration(包声明)
确保一个类具有一个包声明,并且(可选地)包名要与源代码文件所在的目录名相匹配。
解释:位于空包中的类是不能够被导入的。很多开发新手并没有注意到这一点。
Parameter Assignment(参数赋值)
不允许对参数进行赋值。
Redundant Throws(多余的throws)
检查throws子句中是否声明了多余的异常,例如重复异常、未检查的异常或一个已声明抛出的异常的子类。
Require This(需要this)
检查代码是否使用了“this.”,也就是说,在默认情况下,引用当前对象的实例变量和方法时,应当显式地通过“this.varName”或“this.methodName(args)”这种形式进行调用。
Return Count(return总数)
限制return语句的数量。默认值为2。可以忽略检查指定的方法(默认忽略equals()方法)。
解释:过多的返回点可能表明代码尝试处理过多的业务,可能会难以理解。
Simplify Boolean Expression(简化布尔表达式)
检查是否有过于复杂的布尔表达式。现在能够发现诸如if (b == true)、b || true、!false等类型的代码。
解释:复杂的布尔逻辑会使得代码难以理解和维护。
Simplify Boolean Return(简化布尔返回值)
检查是否有过于复杂的布尔类型return语句。
String Literal Equality(严格的常量等式比较)
检查字符串对象的比较是否使用了==或!=运算符。
解释:Java新手程序员经常会使用类似于下面的代码:
SuperClone(父类clone方法)
检查一个覆盖的clone()方法是否调用了super.clone()方法。
参考:Object.clone()。
SuperFinalize(父类finalize方法)
检查一个覆盖的finalize()方法是否调用了super.finalize()方法。
参考:清理未使用对象。
Trailing Array Comma(数组尾随逗号)
检查数组的初始化是否包含一个尾随逗号。
解释:添加尾随逗号可以使得改变元素顺序,或者在末尾添加新的元素变得更加方便。
Unnecessary Parentheses(不必要的圆括号)
检查代码中是否使用了不必要的圆括号。
One Statement Per Line(每行一条语句)
检查每行是否只有一条语句。

12> Class Design(类设计:8个)
Designed For Extension(设计扩展性)
检查类是否具有可扩展性。更准确地说,它强制使用一种编程风格,父类必须提供空的“句柄”,以便于子类实现它们。
确切的规则是,类中可以由子类继承的非私有、非静态方法必须是:
1. abstract方法,或
2. final方法,或
3. 有一个空的实现
解释:这种API设计风格可以保护父类不会被子类破坏。不利之处在于子类的灵活性会受到限制,特别是它们不能够阻止父类代码的执行,但是这也意味着子类不会由于忘记调用父类的方法而破坏父类的状态。
Final Class(final类)
检查一个只有私有构造器的类是否被声明为final。
Inner Type Last(最后声明内部类型)
检查嵌套/内部的类型是否在当前类的最底部声明(在所有的方法/字段的声明之后)。
Hide Utility Class Constructor(隐藏工具类构造器)
确保工具类(在API中只有静态方法和字段的类)没有任何公有构造器。
解释:实例化工具类没有任何意义。因此,工具类的构造器应当是私有的或者受保护的(如果你打算以后扩展子类)。一个常见的错误便是忘记隐藏默认构造器。
Interface Is Type(接口是类型)
Bloch编写的《Effective Java》中提到,接口应当描述为一个类型。因此,定义一个只包含常量,但是没有包含任何方法的接口是不合适的。标准类javax.swing.SwingConstants是一个会被这项检查标记的示例类。
这项检查还可以配置为禁用标记接口,例如java.io.Serializable,这种接口不会包含任何方法或常量。
Mutable Exception(可变异常)
确保异常(异常类的名称必须匹配指定的正则表达式)是不可变的。也就是说,异常只能有final字段。
Throws Count(抛出计数)
将异常抛出语句的数量配置为一个指定的限值(默认值为1)。
解释:异常是方法接口的组成部分之一。如果一个方法声明抛出过多不同的异常,就会使得异常处理非常繁重,并且会导致不好的编程习惯,例如catch (Exception)。这项检查会强制开发者将异常处理变得具有层次性。
Visibility Modifier(可见性标识符)
检查类成员的可见性。只有static final的类成员可以是公有的,其他的类成员必须是私有的,除非设置了protectedAllowed属性或packageAllowed属性。
如果类成员的名称和指定的公有成员正则表达式匹配,那么这项检查就不会标记这个类成员(默认包含“^serialVersionUID$”)。
解释:强制封装。

13> Duplicates(重复:1个)
Strict Duplicate Code(严格重复代码)
逐行地比较所有的代码行,如果有若干行只有缩进有所不同,那么就报告存在重复代码。Java代码中的所有的import语句都会被忽略,任何其他的行 —— 包括Javadoc、方法之间的空白行,等等 —— 都会检查。

14> Metrics(度量:6个)
Boolean Expression Complexity(布尔表达式复杂度)
限制一个表达式中的&&、||、&、|、^等逻辑运算符的数量。
解释:过多的条件会导致代码难以读懂、调试和维护。
注意,&和|运算符并不仅仅是整数的位运算符,它们还是布尔运算符&&和||的非快捷版本。
Class Data Abstraction Coupling(类的数据抽象耦合)
这项度量会测量给定类中的其他类的实例化操作的次数。这种类型的耦合并不是由于继承或者面向对象范型而产生的。一般而言,任何将其他抽象数据类型作为成员的抽象数据类型都具有数据抽象耦合;因此,如果一个类中的某个局部变量是另一个类的实例(对象),那么就存在数据抽象耦合(DAC)。DAC越高,系统的数据结构(类)就会越复杂。
Class Fan Out Complexity(类的扇出复杂度)
一个给定类所依赖的其他类的数量。这个数量的平方还可以用于表示函数式程序(基于文件)中需要维护总量的最小值。
Cyclomatic Complexity(循环复杂度)
检查循环复杂度是否超出了指定的限值。该复杂度由构造器、方法、静态初始化程序、实例初始化程序中的if、while、do、for、?:、catch、switch、case等语句,以及&&和||运算符的数量所测量。它是遍历代码的可能路径的一个最小数量测量,因此也是需要的测试用例的数量。通常1-4是很好的结果,5-7较好,8-10就需要考虑重构代码了,如果大于11,则需要马上重构代码!
Non Commenting Source Statements(非注释源码语句)
通过对非注释源码语句(NCSS)进行计数,确定方法、类、文件的复杂度。这项检查遵守Chr. Clemens Lee编写的JavaNCSS-Tool中的规范。
粗略地说,NCSS度量就是不包含注释的源代码行数,(近似)等价于分号和左花括号的计数。一个类的NCSS就是它所有方法的NCSS、它的内部类的NCSS、成员变量声明数量的总和。一个文件的NCSS就是它所包含的所有顶层类的NCSS、imports语句和包声明语句数量的总和。
解释:太大的方法和类会难以阅读,并且维护成本会很高。一个较大的NCSS数值通常意味着对应的方法或类承担了过多的责任和/或功能,应当分解成多个较小的单元。
NPath Complexity(NPath复杂度)
NPATH度量会计算遍历一个函数时,所有可能的执行路径的数量。它会考虑嵌套的条件语句,以及由多部分组成的布尔表达式(例如,A && B,C || D,等等)。
解释:在Nejmeh的团队中,每个单独的例程都有一个取值为200的非正式的NPATH限值;超过这个限值的函数可能会进行进一步的分解,或者至少一探究竟。

15> Miscellaneous(杂项:12个)
Array Type Style(数组类型风格)
检查数组定义的风格。有的开发者使用Java风格:public static void main(String[] args);有的开发者使用C风格:public static void main(String args[])。
Descendent Token Check(后续标记检查)
检查在其他标记之下的受限标记。
警告:这是一项非常强大和灵活的检查,但是与此同时,它偏向于底层技术,并且非常依赖于具体实现,因为,它的结果依赖于我们用来构建抽象语法树的语法。因此,当其他检查项目提供了你想要用的功能时,我们建议你使用这些检查项目。总之,这项检查只能在抽象语法树的层面上工作,它并不了解任何语言结构。
Final Parameters(final参数)
检查方法/构造器的参数是否是final的。这项检查会忽略接口方法的检查 —— final关键字不会理会接口方法的参数,因为没有任何代码能够修改这些参数。
解释:在方法算法的执行期间改变参数值会使读者产生混淆,因此应当避免这种情况的发生。有个很好的方法可以使得Java的编译器预防这种编码风格,那就是将方法的参数声明为final的。
Indentation(代码缩进)
检查Java代码的缩进是否正确。
尽管有些格式精美的打印机有时可以很方便地批量重排原始代码的格式,但是它们通常不是没有足够的可配置性,就是不能够达到预期的排版格式。有时这是个人喜好的问题,有时这是实际经验的问题。无论如何,这项检查应当只确保代码遵守缩进规则的一个最小集合。
New Line At End Of File(文件末尾的新行)
检查文件是否以新行结束。
解释:通常,任何源码文件和文本文件都应当以一个新行符结束,特别是使用诸如CVS这样的SCM系统时。当文件没有以新行结束时,CVS甚至会打印出一个警告。
Todo Comment(TODO注释)
这项检查负责TODO注释的检查。实际上,这是一种检查Java注释的通用正则表达式匹配器。想要检查其他格式的Java注释,那么设置format属性即可。
Translation(语言转换)
这是一项FileSetCheck检查,通过检查关键字的一致性属性文件,它可以确保代码的语言转换的正确性。可以使用两个描述同一个上下文环境的属性文件来保证一致性,如果它们包含相同的关键字。
Trailing Comment(行尾注释)
这项检查可以确保代码中含有注释的行中只包含注释。在使用//注释的场合下,这意味着//符号之前只能有空格。如果行不是以注释结束的,那么就不会检查这些注释。
Uncommented Main(未注释main方法)
检查源码中是否有未注释的main()方法(调试的残留物)。
Upper Ell(大写“L”)
检查long类型的常量在定义时是否由大写的“L”开头。注意,是“L”,不是“l”。这是由《Java Language Specification》的第3.10.1章节所建议的编码规约。
解释:小写字母“l”看起来非常像数字“1”。
Regexp(正则表达式)
这项检查可以确保指定的格式串在文件中存在,或者允许出现几次,或者不存在。
这项检查结合了RegexpHeader、GenericIllegalRegexp和RequiredRegexp的所有功能,但是并不支持使用文件中正则表达式

16> Other(其他:2个)
Checker(检查器)
每个checkstyle配置的根模块。不能被删除。
TreeWalker(树遍历器)
FileSetCheck TreeWalker会检查单个的Java源码文件,并且定义了适用于检查这种文件的属性。

17> Filters(过滤器:4个)
Severity Match Filter(严重度匹配过滤器)
SeverityMatchFilter过滤器会根据事件的严重级别决定是否要接受审计事件。
Suppression Filter(抑制过滤器)
在检查错误时,SuppressionFilter过滤器会依照一个XML格式的策略抑制文件,选择性地拒绝一些审计事件。如果没有配置好的策略抑制文件可用,那么这个过滤器会接受所有的审计事件。
Suppression Comment Filter(抑制注释过滤器)
SuppressionCommentFilter过滤器使用配对的注释来抑制审计事件。