本文目录导读:

我将为您提供一个完整的Checkstyle配置和违规案例演示。
项目结构
checkstyle-demo/
├── pom.xml
├── checkstyle.xml
├── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ ├── UserService.java
│ └── User.java
Checkstyle配置文件 (checkstyle.xml)
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="error"/>
<property name="fileExtensions" value="java"/>
<!-- 排除文件 -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<!-- 检查文件中的Tab键 -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<!-- 文件长度 -->
<module name="FileLength">
<property name="max" value="2000"/>
</module>
<module name="TreeWalker">
<!-- Javadoc 注释检查 -->
<module name="JavadocType">
<property name="scope" value="public"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingReturnType" value="false"/>
<property name="allowedAnnotations" value="Override"/>
</module>
<!-- 命名规范 -->
<module name="ClassTypeParameterName">
<property name="format" value="^[A-Z][A-Z0-9]*$"/>
</module>
<module name="ConstantName"/>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<module name="TypeName"/>
<!-- 代码块检查 -->
<module name="LeftCurly">
<property name="option" value="eol"/>
</module>
<module name="RightCurly">
<property name="option" value="same"/>
</module>
<module name="NeedBraces"/>
<!-- 空格检查 -->
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyTypes" value="true"/>
</module>
<!-- 导入检查 -->
<module name="AvoidStarImport"/>
<module name="UnusedImports"/>
<module name="RedundantImport"/>
<!-- 代码复杂度检查 -->
<module name="CyclomaticComplexity">
<property name="max" value="10"/>
</module>
<module name="JavaNCSS">
<property name="methodMaximum" value="50"/>
</module>
<!-- 代码格式检查 -->
<module name="LineLength">
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://"/>
</module>
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="4"/>
</module>
<!-- 其他检查 -->
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StringLiteralEquality"/>
</module>
</module>
具有违规的示例代码
User.java (包含违规)
package com.example;
import java.util.*;
import java.math.BigDecimal;
import java.util.ArrayList;
/**
* 用户实体
* @author
*/
public class user { // 违规1: 类名小写
private String name;
private int age;
private String email;
public String publicField; // 违规2: public字段
// 违规3: 缺少Javadoc
public user() {
name = "unknown";
}
// 违规4: 方法命名不规范
public void getuserinfo() { // 应为 camelCase getUserInfo
String user_name = "test"; // 违规5: 局部变量命名
INTEGER count = 0; // 违规6: 使用包装类型作为基本类型
for(int i = 0; i < 5; i++) { // 违规7: 缺少空格
if(count == 1)
{
System.out.println("one"); // 违规8: 花括号位置
} else {
System.out.println(count);
}
}
// 违规9: 魔法数字
int days = 365;
// 违规10: 简化布尔表达式
if(count > 0 == true) {
System.out.println("positive");
}
}
// 违规11: 方法过长且复杂度高
public void complexMethod(int a, int b, int c) {
if(a > 0) {
if(b > 0) {
if(c > 0) {
if(a > b) {
if(b > c) {
if(a > c) {
System.out.println("complex1");
} else {
System.out.println("complex2");
if(a == c) {
System.out.println("complex3");
}
}
} else {
System.out.println("complex4");
if(c > a) {
System.out.println("complex5");
}
}
} else {
System.out.println("complex6");
if(c > a) {
if(c > b) {
System.out.println("complex7");
} else {
if(b > a) {
System.out.println("complex8");
}
}
}
}
}
}
}
}
// 违规12: 缺少默认switch
public String getDayType(int day) {
String type;
switch(day) {
case 1:
case 2:
case 3:
case 4:
case 5:
type = "工作日";
break;
case 6:
case 7:
type = "周末";
break;
}
return type;
}
}
Maven配置 (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>checkstyle-demo</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<checkstyle.version>9.3</checkstyle.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<linkXRef>false</linkXRef>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
运行Checkstyle
# 运行Checkstyle检查 mvn checkstyle:check # 生成Checkstyle报告 mvn checkstyle:report # 完整构建时执行检查 mvn verify
Checkstyle输出示例
[INFO] There is 1 error reported:
[INFO]
[INFO] Starting audit...
[ERROR] User.java:8:1: Type name 'user' must match pattern '^[A-Z][a-zA-Z0-9]*$'. [TypeName]
[ERROR] User.java:11: Type Javadoc comment is missing an @author tag. [JavadocType]
[ERROR] User.java:12:5: Variable 'publicField' must be private and have accessor methods. [VisibilityModifier]
[ERROR] User.java:16:5: Missing a Javadoc comment. [JavadocMethod]
[ERROR] User.java:21:17: Method name 'getuserinfo' must match pattern '^[a-z][a-zA-Z0-9]*$'. [MethodName]
[ERROR] User.java:22:13: Local variable name 'user_name' must match pattern '^[a-z][a-zA-Z0-9]*$'. [LocalVariableName]
[ERROR] User.java:23:13: Local variable name 'count' must match pattern '^[a-z][a-zA-Z0-9]*$'. [LocalVariableName]
[ERROR] User.java:25:14: 'for' is not followed by whitespace. [WhitespaceAround]
[ERROR] User.java:28:17: '{' should be on the previous line. [LeftCurly]
[ERROR] User.java:31:13: '}' should be on the same line. [RightCurly]
[ERROR] User.java:33:13: Magic number '365' - use a constant. [MagicNumber]
[ERROR] User.java:37:22: Avoid use of equality operator '==' with boolean expression. [SimplifyBooleanExpression]
[ERROR] User.java:72:9: Switch without 'default' clause. [MissingSwitchDefault]
[ERROR] User.java:6:1: Unused import - java.util.ArrayList. [UnusedImports]
[ERROR] User.java:5:1: Using the '.*' form of import should be avoided - java.util.*. [AvoidStarImport]
[ERROR] User.java:7:1: Redundant import from the same package - java.util.ArrayList. [RedundantImport]
修正后的代码参考
package com.example;
import java.util.HashMap;
import java.util.Map;
/**
* 用户实体
*
* @author YourName
* @version 1.0
*/
public class User {
private static final int DAYS_IN_YEAR = 365;
private static final int MAX_COMPLEXITY = 10;
private String name;
private int age;
private String email;
/**
* 默认构造函数
*/
public User() {
this.name = "unknown";
this.age = 0;
this.email = "";
}
/**
* 获取用户信息
*
* @return 用户信息字符串
*/
public String getUserInfo() {
String userName = "test";
int userAge = 18;
for (int i = 0; i < userName.length(); i++) {
if (userAge > MAX_COMPLEXITY) {
System.out.println("Age is large");
} else {
System.out.println(userName.indexOf(userName.charAt(i)));
}
}
int days = DAYS_IN_YEAR;
return userName + " " + userAge + " " + days;
}
/**
* 获取星期类型
*
* @param day 日期
* @return 类型描述
*/
public String getDayType(int day) {
String type;
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
type = "工作日";
break;
case 6:
case 7:
type = "周末";
break;
default:
type = "无效日期";
break;
}
return type;
}
}
这个案例展示了Checkstyle的主要功能:
- 命名规范 - 类名、方法名、变量名
- 代码格式 - 缩进、空格、行长度
- Javadoc要求 - 必须为公共方法添加注释
- 复杂度控制 - 限制圈复杂度
- 导入管理 - 避免通配符导入、检查未使用的导入
- 最佳实践 - 避免魔法数字、简化布尔表达式
通过定期运行Checkstyle,可以确保代码质量和一致性,使团队协作更加顺畅。