data: demo-pmd 每文件审核报告入库(26 份,绝对路径规范化)

This commit is contained in:
范智鹏
2026-08-26 22:29:47 +08:00
parent 3c390cfa90
commit 3a66aa538f
26 changed files with 4943 additions and 0 deletions
@@ -0,0 +1,70 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\bestpractices\extra\AccessorAndIpDemo.java`
**语言:** java
**耗时:** 131.2s
**分析工具:** pmd
---
总计: 17 | 错误: 3 | 警告: 13 | 建议: 1
静态分析 · 14 个问题
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L10
该类只有私有构造函数,应声明为 final。
建议: 将类声明为 `final`,防止继承。如果类需要被实例化,应将私有构造函数改为包私有或 public。
- 🔴 `pmd:SystemPrintln` L42
使用了 `System.out/err` 输出。
建议: 在生产代码中应使用日志框架(如 SLF4J)替代 `System.out.println`。例如定义 `private static final Logger LOG = LoggerFactory.getLogger(MiscMain.class);`,并调用 `LOG.info("demo misc");`
- 🟡 `pmd:MissingStaticMethodInNonInstantiatableClass` L10
类无法被实例化,且未提供任何静态方法或静态字段。
建议: 如果该类是工具类,应声明为 final 并提供静态方法或静态字段;如果类需要实例化,则应将构造函数改为非私有。例如:声明为 `final class PrivateCtor` 并添加 `public static PrivateCtor getInstance() { return new PrivateCtor(); }`
- 🟡 `pmd:AtLeastOneConstructor` L15
每个类应至少声明一个构造函数。
建议: 为 `UsesPrivateCtor` 添加一个显式构造函数,例如 `UsesPrivateCtor() {}`
- 🟡 `pmd:CommentDefaultAccessModifier` L16
方法 `make()` 缺少默认访问修饰符的注释。
建议: 为方法添加 `/* package-private */``/* default */` 注释,明确默认的包私有访问权限。
- 🟡 `pmd:AtLeastOneConstructor` L22
每个类应至少声明一个构造函数。
建议: 为 `PrivateFieldOwner` 添加一个显式构造函数,例如 `PrivateFieldOwner() {}`
- 🟡 `pmd:ImmutableField` L23
字段 `secret` 可以声明为 final。
建议: 如果字段在初始化后不再改变,请声明为 `private final int secret = 42;`
- 🟡 `pmd:CommentDefaultAccessModifier` L24
方法 `getSecret()` 缺少默认访问修饰符的注释。
建议: 为方法添加 `/* package-private */``/* default */` 注释,明确默认的包私有访问权限。
- 🟡 `pmd:AtLeastOneConstructor` L29
每个类应至少声明一个构造函数。
建议: 为 `ReadsPrivateField` 添加一个显式构造函数,例如 `ReadsPrivateField() {}`
- 🟡 `pmd:CommentDefaultAccessModifier` L30
方法 `read(PrivateFieldOwner)` 缺少默认访问修饰符的注释。
建议: 为方法添加 `/* package-private */``/* default */` 注释,明确默认的包私有访问权限。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L30
参数 `o` 未被赋值,可以声明为 final。
建议: 将参数声明为 `final PrivateFieldOwner o`,表明方法内不会重新赋值。
- 🟡 `pmd:AtLeastOneConstructor` L36
每个类应至少声明一个构造函数。
建议: 为 `HardCodedIpDemo` 添加一个显式构造函数,例如 `HardCodedIpDemo() {}`
- 🟡 `pmd:CommentDefaultAccessModifier` L37
字段 `address` 缺少默认访问修饰符的注释。
建议: 在字段声明前添加 `/* package-private */` 注释,明确访问权限。
- 🟡 `pmd:AvoidUsingHardCodedIP` L37
不要硬编码 IP 地址 `192.168.0.1`
建议: 将 IP 地址放入配置项或属性文件,在代码中通过配置读取。例如:`String address = System.getProperty("app.address", "localhost");`,如果需要使用 Spring 可用 `@Value("${app.address}")`。避免在代码中直接出现 IP 字面量。
AI 审查 · 3 条建议
- 🔴 [AI] [bug] `private-constructor-access` L17
**外部类访问私有构造函数导致编译失败**
UsesPrivateCtor.make() 中 `return new PrivateCtor();` 试图在 PrivateCtor 类外部调用其私有构造函数。根据 Java 访问控制,private 构造函数只能被声明它的类内部访问,因此该代码无法通过编译。需要将构造函数访问级别提升,或改为通过私有类提供的静态工厂方法创建实例。
建议: 将 PrivateCtor 的构造函数由 private 改为包私有(或 public),例如改为 `PrivateCtor()`;或者保留私有构造,同时在 PrivateCtor 内添加 `public static PrivateCtor getInstance()`,并将调用处改为 `PrivateCtor.getInstance()`
- 🟡 [AI] [bug] `null-check-missing` L31
**read() 未对参数进行空值检查**
ReadsPrivateField.read(PrivateFieldOwner o) 直接调用 o.getSecret()。若调用方传入 null,将抛出 NullPointerException。建议增加显式空值检查或使用 java.util.Objects.requireNonNull。
建议: 在方法开头添加 `if (o == null) { throw new NullPointerException("o"); }`;或简化为 `java.util.Objects.requireNonNull(o, "o");`
- 🔵 [AI] [design] `unused-field` L37
**字段 address 声明后从未被使用**
HardCodedIpDemo.address 字段在类中没有任何方法读取或使用它。即便移除硬编码字面量,该字段本身也可能属于无用代码。如果该字段仅用于演示规则,建议删除;如果用于配置,请提供相应的 getter 或实际使用该字段,避免维护困惑。
建议: 删除该字段(类体将保持为空),或为字段添加 getter 并在业务中使用。若采用配置注入,也应确保字段被消费。
@@ -0,0 +1,68 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\AccessorDemo.java`
**语言:** java
**耗时:** 127.9s
**分析工具:** pmd
---
总计: 16 | 错误: 1 | 警告: 10 | 建议: 5
静态分析 · 12 个问题
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L13
该类只有私有构造函数,应声明为 final。
建议: 将类声明改为 final class AccessorClass,保留私有构造函数,明确禁止继承。
- 🟡 `pmd:CommentDefaultAccessModifier` L17
方法 'create()' 缺少默认访问修饰符的注释。
建议: 在方法前添加 /* default */ 注释,明确表达包级私有访问意图。
- 🟡 `pmd:AtLeastOneConstructor` L22
每个类应至少声明一个构造函数。
建议: 为 AccessorUser 添加显式无参构造函数,例如 AccessorUser() {}。
- 🟡 `pmd:CommentDefaultAccessModifier` L23
方法 'bad()' 缺少默认访问修饰符的注释。
建议: 在方法前添加 /* default */ 注释,明确表达包级私有访问意图。
- 🟡 `pmd:UnusedLocalVariable` L25
避免未使用的局部变量 'a'。
建议: 删除该局部变量声明;如果 create() 的返回值确实是需要的,请先使用它。
- 🟡 `pmd:LocalVariableCouldBeFinal` L26
局部变量 'cg' 可以声明为 final。
建议: 将变量声明改为 final CallerGen cg = new CallerGen();。
- 🟡 `pmd:UnusedLocalVariable` L27
避免未使用的局部变量 's'。
建议: 删除该局部变量声明,或使用 getHidden() 的返回值。
- 🟡 `pmd:AtLeastOneConstructor` L32
每个类应至少声明一个构造函数。
建议: 为 CallerGen 添加显式无参构造函数,例如 CallerGen() {}。
- 🟡 `pmd:ImmutableField` L33
字段 'hidden' 可以被声明为 final。
建议: 将字段改为 private final String hidden = "x";,使字段初始化后不可变。
- 🟡 `pmd:CommentDefaultAccessModifier` L35
方法 'getHidden()' 缺少默认访问修饰符的注释。
建议: 在方法前添加 /* default */ 注释,明确表达包级私有访问意图。
- 🔵 `pmd:UnnecessaryImport` L9
未使用的导入 'java.util.ArrayList'
建议: 删除该 import 语句,避免无效依赖。
- 🔵 `pmd:UnnecessaryImport` L10
未使用的导入 'java.util.List'
建议: 删除该 import 语句,避免无效依赖。
AI 审查 · 4 条建议
- 🟡 [AI] [bug] `dead-method` L23
**bad() 方法无任何可观察行为,疑似调试残留**
bad() 创建了 AccessorClass 和 CallerGen 实例,并调用 getHidden(),但所有局部变量与返回值都被丢弃;方法不会写入状态、打印内容或返回结果,因此调用它没有任何可验证的效果。
建议: 删除该方法;如果它用于演示 getter,应返回 getHidden() 结果或使用断言校验,避免空操作。
- 🔵 [AI] [design] `misleading-comment` L12
**注释与代码行为不一致,示例未触发合成访问器**
第 12 行注释声称代码涉及 AccessorClassGeneration,但 AccessorUser 只是调用 AccessorClass.create(),私有构造函数是在 AccessorClass 自身静态方法内调用,不会生成合成访问器。第 31 行也存在类似问题。这样的示例会误导读者,无法验证对应规则。
建议: 删除或改写相关注释,说明当前代码仅用于触发其他 PMD 规则;如需演示合成访问器,可让内部类访问外部类的私有字段,由编译器生成 synthetic accessor 方法。
- 🔵 [AI] [performance] `stateless-factory-allocation` L17
**AccessorClass 是无状态类,create() 每次调用都分配新实例**
AccessorClass 没有实例字段,每次调用 create() 都会 new 一个无状态对象。若该工厂方法被高频调用,会产生不必要的对象分配与 GC 压力。可改为单例持有唯一实例。
建议: 为 AccessorClass 添加 private static final 实例字段,并在 create() 中返回该实例;若类仅作为命名空间,也可直接使用静态方法。
- 🔵 [AI] [design] `misleading-comment-method-generation` L31
**AccessorMethodGeneration 注释与代码行为不符**
第 31 行注释声称“避免合成访问器方法”,但 getHidden() 是 CallerGen 自身的普通方法,直接读取自己的私有字段;外部类只是调用该 getter,并不会触发编译器生成 synthetic accessor method。
建议: 将该注释改为说明性文字;如需演示 AccessorMethodGeneration,应在内部类中访问外部类私有字段。
@@ -0,0 +1,61 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\bestpractices\extra\AccessorGen2.java`
**语言:** java
**耗时:** 163.0s
**分析工具:** pmd
---
总计: 14 | 错误: 3 | 警告: 11 | 建议: 0
静态分析 · 11 个问题
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L14
该类只有私有构造函数,可能应设为 final。
建议: 将内部类 Inner 声明为 final,例如 public final class Inner。
- 🔴 `pmd:SystemPrintln` L38
使用了 System.out/err 输出。
建议: 改用日志框架,例如 System.getLogger("AccMain").info(...),避免直接使用 System.out。
- 🟡 `pmd:AtLeastOneConstructor` L10
类应至少声明一个构造函数。
建议: 为 AccessorClassGen 添加显式构造函数,例如 public AccessorClassGen() {}。
- 🟡 `pmd:CommentDefaultAccessModifier` L11
方法 'method()' 缺少默认访问修饰符的注释。
建议: 在方法声明前添加 /* default */ 注释,或显式指定 public/private/protected 访问修饰符。
- 🟡 `pmd:UnusedLocalVariable` L12
避免使用未使用的局部变量,例如 'ic'。
建议: 直接执行 new Inner() 而不是赋值给未使用的变量,或者直接删除该行。
- 🟡 `pmd:AtLeastOneConstructor` L21
类应至少声明一个构造函数。
建议: 为 AccessorMethodGen 添加显式构造函数,例如 public AccessorMethodGen() {}。
- 🟡 `pmd:UnusedPrivateField` L22
避免使用未使用的私有字段,例如 'counter'。
建议: 为 counter 添加 getter 方法,使其被读取,或删除该字段。
- 🟡 `pmd:CommentDefaultAccessModifier` L25
构造函数 'InnerClass()' 缺少默认访问修饰符的注释。
建议: 在构造函数声明前添加 /* default */ 注释,或显式指定访问修饰符。
- 🟡 `pmd:AtLeastOneConstructor` L32
类应至少声明一个构造函数。
建议: 为 HardCodedIp 添加显式构造函数,例如 HardCodedIp() {}。
- 🟡 `pmd:CommentDefaultAccessModifier` L33
字段 'addr' 缺少默认访问修饰符的注释。
建议: 在字段声明前添加 /* default */ 注释,或显式指定 private/public/protected。
- 🟡 `pmd:AvoidUsingHardCodedIP` L33
不要硬编码 IP 地址 '192.168.1.1'。
建议: 将 IP 地址移入配置文件或环境变量,运行时读取,例如 System.getenv("SERVER_IP"),并校验格式。
AI 审查 · 3 条建议
- 🔴 [AI] [bug] `multiple-public-top-level-classes` L21
**同一源文件中包含多个 public 顶层类**
Java 规定一个 .java 文件只能包含一个 public 顶层类,且类名必须与文件名一致。当前第 10 行 AccessorClassGen 和第 21 行 AccessorMethodGen 均为 public,将导致编译失败。
建议: 将 AccessorMethodGen 改为包私有(去掉 public),或将其拆分为独立的 .java 文件。
- 🟡 [AI] [design] `public-inner-class-with-private-constructor` L14
**内部类 Inner 声明为 public 但构造函数为 privateAPI 设计矛盾**
Inner 被声明为 public,但其构造函数是 private,外部代码(除外部类 AccessorClassGen 外)无法实例化它。这种公开但不可实例化的类型会困惑调用方,应缩小可见性。
建议: 将 Inner 改为 private 嵌套类;若同时满足 PMD 建议,可改为 private final class Inner。
- 🟡 [AI] [bug] `write-only-field` L22
**counter 字段只写不读,自增操作无任何效用**
AccessorMethodGen.InnerClass 构造函数中执行 counter++,但 counter 从未被任何方法读取,该状态变化不可观测。PMD 的 UnusedPrivateField 提示了字段未使用,但更深层的问题是递增操作本身没有对应读取方,可能表明逻辑未完成或存在缺陷。
建议: 为 counter 添加 getter 方法以便读取计数,或移除该字段及递增语句。
@@ -0,0 +1,53 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\AfterBeforeTest.java`
**语言:** java
**耗时:** 121.3s
**分析工具:** pmd
---
总计: 11 | 错误: 2 | 警告: 9 | 建议: 0
静态分析 · 7 个问题
- 🔴 `pmd:SystemPrintln` L27
使用了 System.out 或 System.err 进行控制台输出。
建议: 建议用日志框架替代 System.out,例如 java.util.logging.Logger 的 info 方法。若为一次性调试代码,可在最终版本删除。
- 🟡 `pmd:AtLeastOneConstructor` L8
每个类都应声明至少一个构造函数。
建议: 请为类 MissingAfterTest 添加一个显式构造函数,例如 public MissingAfterTest() {}。若不允许实例化,可设为 private。
- 🟡 `pmd:TestClassWithoutTestCases` L8
类 'MissingAfterTest' 可能是一个测试类,但它不包含任何测试用例。
建议: 如果该类是测试类,请添加一个带有 @Test 注解的测试方法;若不需要测试,请删除该类或重命名为非测试类名称。添加注解时需引入 JUnit 依赖。
- 🟡 `pmd:AtLeastOneConstructor` L14
每个类都应声明至少一个构造函数。
建议: 请为类 MissingBeforeTest 添加一个显式构造函数,例如 public MissingBeforeTest() {}。若不允许实例化,可设为 private。
- 🟡 `pmd:TestClassWithoutTestCases` L14
类 'MissingBeforeTest' 可能是一个测试类,但它不包含任何测试用例。
建议: 如果该类是测试类,请添加一个带有 @Test 注解的测试方法;若不需要测试,请删除该类或重命名为非测试类名称。添加注解时需引入 JUnit 依赖。
- 🟡 `pmd:AtLeastOneConstructor` L20
每个类都应声明至少一个构造函数。
建议: 请为类 MissingTestAnn 添加一个显式构造函数,例如 public MissingTestAnn() {}。若不允许实例化,可设为 private。
- 🟡 `pmd:UnitTestShouldUseTestAnnotation` L21
单元测试应使用 @Test 注解,否则不会运行。若是 JUnit Jupiter,测试方法可使用 @RepeatedTest@TestFactory@TestTemplate@ParameterizedTest 注解替代。
建议: 为 testSomething 方法添加 @Test 注解(JUnit 4/5),或根据场景改用 @RepeatedTest/@TestFactory/@TestTemplate/@ParameterizedTest
AI 审查 · 4 条建议
- 🔴 [AI] [bug] `multiple-public-classes-in-file` L14
**一个源文件中存在多个 public 类,无法编译**
Java 允许一个源文件中最多有一个 public 顶层类,且必须与文件名一致。当前文件中第 8、14、20 行分别声明了 MissingAfterTest、MissingBeforeTest、MissingTestAnn 三个 public 类,导致编译失败。
建议: 将 MissingBeforeTest 和 MissingTestAnn 改为包级私有(去掉 public),或拆分到独立文件。若文件名不是 MissingAfterTest.java,还需要调整类名或文件名使二者一致。
- 🟡 [AI] [bug] `missing-junit-imports` L5
**使用 JUnit 注解前未导入相关包**
代码中已有 tearDown/setUp/testSomething 等测试相关方法,后续修复需要添加 @After/@Before/@Test 注解,但当前没有任何 JUnit 的 import 语句,添加注解后将因找不到符号而编译失败。
建议: 在文件顶部添加 JUnit 4 导入,例如 import org.junit.After; import org.junit.Before; import org.junit.Test;。如果使用 JUnit 5,请改为导入 org.junit.jupiter.api.*。同时确保 classpath 包含 JUnit 依赖。
- 🟡 [AI] [design] `empty-lifecycle-method` L9
**空的 setUp/tearDown 生命周期方法没有实际作用**
MissingAfterTest.tearDown 与 MissingBeforeTest.setUp 方法体为空,即使补充 @After/@Before 注解,也不会执行任何初始化或清理逻辑,容易引入误导。
建议: 在方法中实现实际的资源初始化/清理逻辑;如果不需要,则删除这两个空方法。
- 🟡 [AI] [design] `missing-assertions-in-test` L21
**testSomething 方法缺少断言,测试无效**
MissingTestAnn.testSomething 方法即使添加 @Test 注解,也因为没有断言而无法验证任何行为,空测试会通过并掩盖回归问题。
建议: 在该方法中补充实际的断言,例如使用 org.junit.jupiter.api.Assertions 中的 assertEquals、assertNotNull 等方法,验证被测对象的行为和预期结果。
@@ -0,0 +1,30 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\api\ApiService.java`
**语言:** java
**耗时:** 74.4s
**分析工具:** pmd
---
总计: 4 | 错误: 1 | 警告: 2 | 建议: 1
静态分析 · 2 个问题
- 🔴 `pmd:SystemPrintln` L11
使用了 System.out/err 进行输出
建议: 改用日志框架输出,例如:private static final java.util.logging.Logger LOGGER = java.util.logging.Logger.getLogger(ApiService.class.getName()); 然后调用 LOGGER.info("api service");。这样支持日志级别、格式化与可配置化输出。
- 🟡 `pmd:AtLeastOneConstructor` L9
每个类应至少声明一个构造函数
建议: 为 ApiService 类添加一个显式构造函数,例如:public ApiService() { }。这样可以显式控制实例化过程,并为后续可能的依赖注入留出扩展点。
AI 审查 · 2 条建议
- 🟡 [AI] [design] `static-method` L10
**doWork 方法不访问实例状态,应声明为 static**
doWork() 方法只执行输出操作,未使用任何实例字段或实例方法,因此没有理由要求调用方创建 ApiService 实例。声明为 static 后,可通过 ApiService.doWork() 直接调用,避免不必要的对象分配,也更清晰地表达其工具方法语义。
建议: 将方法签名改为 public static void doWork(),并更新调用方为 ApiService.doWork()。
- 🔵 [AI] [style] `magic-string` L11
**魔法字符串 "api service" 应提取为常量**
字符串字面量 "api service" 直接出现在代码中,若消息内容在别处也需要使用,重复字面量容易导致不一致。建议提取为静态常量或使用资源文件,提升可维护性与可测试性。
建议: 在类中定义 private static final String MESSAGE = "api service";,并将输出语句改为 System.out.println(MESSAGE);。
@@ -0,0 +1,54 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\AssertStmtTest.java`
**语言:** java
**耗时:** 112.2s
**分析工具:** pmd
---
总计: 12 | 错误: 4 | 警告: 7 | 建议: 1
静态分析 · 10 个问题
- 🔴 `pmd:WrongTestAnnotation` L10
org.junit.Test 注解来自 JUnit 4,而当前代码库使用的是 JUnit Jupiter。
建议: 将 import org.junit.Test; 改为 import org.junit.jupiter.api.Test;,并确保使用 JUnit Jupiter 依赖。
- 🔴 `pmd:WrongTestAnnotation` L19
org.junit.Test 注解来自 JUnit 4,而当前代码库使用的是 JUnit Jupiter。
建议: 改用在 JUnit Jupiter 下用 assertThrows 断言异常:将 @Test(expected = ArithmeticException.class) 改为 @Test,并在方法内使用 Assertions.assertThrows 包裹除零逻辑。
- 🔴 `pmd:SystemPrintln` L27
使用了 System.out/err 输出。
建议: 建议使用日志框架(如 java.util.logging、SLF4J)替代 System.out 输出。
- 🟡 `pmd:AtLeastOneConstructor` L9
每个类应至少声明一个构造函数
建议: 为 AssertStmtTest 类显式添加一个构造函数,例如:public AssertStmtTest() {}
- 🟡 `pmd:UnitTestShouldIncludeAssert` L11
该单元测试应包含 assert() 或 fail()。
建议: 在测试方法中增加断言,例如使用 org.junit.jupiter.api.Assertions.assertEquals(1, x) 替代 assert x == 1。
- 🟡 `pmd:LocalVariableCouldBeFinal` L12
局部变量 'x' 可以声明为 final。
建议: 将 int x = 1; 改为 final int x = 1;,表示变量初始化后不再变化。
- 🟡 `pmd:AssertStatementInTest` L13
测试代码中不应使用 assert 语句。
建议: 不要使用 Java 关键字 assert,改用 JUnit 断言方法,例如 assertEquals(1, x)。
- 🟡 `pmd:AtLeastOneConstructor` L18
每个类应至少声明一个构造函数
建议: 为 JUnitExpectedTest 类显式添加一个构造函数,例如:JUnitExpectedTest() {}。
- 🟡 `pmd:PublicMemberInNonPublicType` L20
公共成员 'testExpected' 声明在非公共类型中。
建议: 由于一个 .java 文件只能有一个 public 类,此处应将测试方法改为包私有可见性:将 public void testExpected() 改为 void testExpected()。
- 🟡 `pmd:UnusedLocalVariable` L21
避免未使用的局部变量 'x'。
建议: 删除未使用的变量,或直接在断言 lambda 中使用该表达式,例如:assertThrows(ArithmeticException.class, () -> { int zero = 0; if (1 / zero == 0) {} })。
AI 审查 · 2 条建议
- 🔴 [AI] [bug] `constant-division-by-zero` L21
**常量除零导致编译失败**
第21行的 `int x = 1 / 0;` 中,1 和 0 都是整数常量表达式,Java 编译器会在编译期直接计算并报错 'division by zero',导致整个源文件无法编译。PMD 未检查编译期错误,因此需要手动修复。
建议: 将除数改为非常量表达式,例如使用变量 `int zero = 0; int x = 1 / zero;`,或者改用 `assertThrows(ArithmeticException.class, () -> { int zero = 0; if (1 / zero == 0) {} })`,确保除零发生在运行时。
- 🔵 [AI] [design] `no-private-constructor-for-main-class` L25
**包含 main 方法的类未提供私有构造函数**
AssertMain 是一个仅包含静态 main 方法的入口类,不应被实例化。建议添加私有构造函数,避免外部创建实例,同时满足构造相关设计约束。
建议: 在 AssertMain 类中添加私有构造函数:`private AssertMain() { throw new AssertionError(); }`,并将类声明为 final(可选)。
@@ -0,0 +1,1078 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\bpcs\BestPracticesCodeStyle.java`
**语言:** java
**耗时:** 290.6s
**分析工具:** pmd
---
总计: 524 | 错误: 78 | 警告: 416 | 建议: 30
静态分析 · 517 个问题
- 🔴 `pmd:SystemPrintln` L51
Usage of System.out/err
- 🔴 `pmd:ImplicitFunctionalInterface` L109
Annotate this interface with @FunctionalInterface or with @SuppressWarnings("PMD.ImplicitFunctionalInterface") to clarify your intent.
- 🔴 `pmd:AvoidFileStream` L130
Avoid instantiating FileInputStream, FileOutputStream, FileReader, or FileWriter
- 🔴 `pmd:SystemPrintln` L158
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L159
Usage of System.out/err
- 🔴 `pmd:AvoidFileStream` L166
Avoid instantiating FileInputStream, FileOutputStream, FileReader, or FileWriter
- 🔴 `pmd:AvoidFileStream` L176
Avoid instantiating FileInputStream, FileOutputStream, FileReader, or FileWriter
- 🔴 `pmd:AvoidThrowingRawExceptionTypes` L240
Avoid throwing raw exception type RuntimeException.
- 🔴 `pmd:AvoidReassigningParameters` L259
Avoid reassigning parameters such as 'x'
- 🔴 `pmd:AvoidThrowingRawExceptionTypes` L359
Avoid throwing raw exception type RuntimeException.
- 🔴 `pmd:SystemPrintln` L384
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L392
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L401
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L410
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L448
Usage of System.out/err
- 🔴 `pmd:FieldNamingConventions` L458
The constant name 'log' doesn't match '[A-Z][A-Z_0-9]*'
- 🔴 `pmd:GuardLogStatement` L461
Logger calls should be surrounded by log level guards.
- 🔴 `pmd:SystemPrintln` L480
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L508
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L523
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L539
Usage of System.out/err
- 🔴 `pmd:ClassNamingConventions` L554
The class name 'Bad$Name' doesn't match '[A-Z][a-zA-Z0-9]*'
- 🔴 `pmd:ClassNamingConventions` L582
The class name 'badClassName' doesn't match '[A-Z][a-zA-Z0-9]*'
- 🔴 `pmd:SystemPrintln` L607
Usage of System.out/err
- 🔴 `pmd:EmptyMethodInAbstractClassShouldBeAbstract` L621
An empty method in an abstract class should be abstract instead
- 🔴 `pmd:FieldNamingConventions` L638
The field name 'bad_name' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:FinalParameterInAbstractMethod` L643
Final parameter in abstract method
- 🔴 `pmd:FormalParameterNamingConventions` L658
The method parameter name 'bad_param' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:SystemPrintln` L668
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L670
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L693
Usage of System.out/err
- 🔴 `pmd:LocalVariableNamingConventions` L700
The local variable name 'bad_var' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:SystemPrintln` L701
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L708
Usage of System.out/err
- 🔴 `pmd:MethodNamingConventions` L714
The instance method name 'BadMethod' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:ModifierOrder` L720
Missorted modifiers `static public`.
- 🔴 `pmd:ModifierOrder` L722
Missorted modifiers `final private`.
- 🔴 `pmd:SystemPrintln` L739
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L740
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L741
Usage of System.out/err
- 🔴 `pmd:StringInstantiation` L796
Avoid instantiating String objects; this is usually unnecessary.
- 🔴 `pmd:ImplicitFunctionalInterface` L805
Annotate this interface with @FunctionalInterface or with @SuppressWarnings("PMD.ImplicitFunctionalInterface") to clarify your intent.
- 🔴 `pmd:SystemPrintln` L812
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L821
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L834
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L842
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L851
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L869
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L877
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L878
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L879
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L880
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L881
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L882
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L888
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L926
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L943
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L951
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L952
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L953
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L954
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L958
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L986
Usage of System.out/err
- 🔴 `pmd:AvoidUsingNativeCode` L1006
The use of native code is not recommended.
- 🔴 `pmd:SystemPrintln` L1025
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1026
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1027
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1028
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1029
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1030
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1031
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1032
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1033
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1034
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1038
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1044
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1053
Usage of System.out/err
- 🟡 `pmd:TooManyStaticImports` L29
Too many static imports may lead to messy code
- 🟡 `pmd:AtLeastOneConstructor` L48
Each class should declare at least one constructor
- 🟡 `pmd:AbstractClassWithoutAbstractMethod` L48
This abstract class does not have any abstract methods
- 🟡 `pmd:PublicMemberInNonPublicType` L50
Public member 'start' declared in a non-public type
- 🟡 `pmd:CommentDefaultAccessModifier` L59
Missing commented default access modifier on constructor 'DataProcessor(String[])'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L59
Parameter 'input' is not assigned and could be declared final
- 🟡 `pmd:ArrayIsStoredDirectly` L60
The user-supplied array 'input' is stored directly.
- 🟡 `pmd:PublicMemberInNonPublicType` L63
Public member 'getItems' declared in a non-public type
- 🟡 `pmd:MethodReturnsInternalArray` L64
Returning 'items' may expose an internal array.
- 🟡 `pmd:AvoidMessageDigestField` L71
You shouldnt declare field of MessageDigest type, because unsynchronized access could cause problems
- 🟡 `pmd:UnusedPrivateField` L71
Avoid unused private fields such as 'digest'.
- 🟡 `pmd:CommentDefaultAccessModifier` L73
Missing commented default access modifier on constructor 'Hasher()'
- 🟡 `pmd:AvoidCatchingGenericException` L76
Avoid catching Exception in try-catch block
- 🟡 `pmd:AtLeastOneConstructor` L83
Each class should declare at least one constructor
- 🟡 `pmd:AvoidStringBufferField` L84
StringBuffers can grow quite a lot, and so may become a source of memory leak (if the owning class has a long life time).
- 🟡 `pmd:ImmutableField` L84
Field 'sb' may be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L86
Missing commented default access modifier on method 'add(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L86
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L92
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L93
Missing commented default access modifier on field 'host'
- 🟡 `pmd:ConstantsInInterface` L98
Using constants in interfaces is a bad practice.
- 🟡 `pmd:AtLeastOneConstructor` L102
Each class should declare at least one constructor
- 🟡 `pmd:UseConcurrentHashMap` L103
If you run in Java5 or newer and have concurrent access, you should use the ConcurrentHashMap implementation
- 🟡 `pmd:CommentDefaultAccessModifier` L103
Missing commented default access modifier on field 'map'
- 🟡 `pmd:UseDiamondOperator` L103
Explicit type arguments can be replaced by a diamond: `new HashMap<>()`
- 🟡 `pmd:DoubleBraceInitialization` L103
Double-brace initialization should be avoided
- 🟡 `pmd:AtLeastOneConstructor` L114
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L115
Missing commented default access modifier on method 'outer()'
- 🟡 `pmd:AvoidLiteralsInIfCondition` L119
Avoid using literals such as 2 in if statements
- 🟡 `pmd:AtLeastOneConstructor` L128
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L129
Missing commented default access modifier on method 'read()'
- 🟡 `pmd:CloseResource` L130
Ensure that resources like this FileInputStream object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L130
Local variable 'fis' could be declared final
- 🟡 `pmd:CloseResource` L131
Ensure that resources like this InputStreamReader object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L131
Local variable 'isr' could be declared final
- 🟡 `pmd:RelianceOnDefaultCharset` L131
Specify a character set instead of relying on the default charset
- 🟡 `pmd:CloseResource` L132
Ensure that resources like this BufferedReader object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L132
Local variable 'br' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L138
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L139
Missing commented default access modifier on method 'list()'
- 🟡 `pmd:LooseCoupling` L140
Avoid using implementation types like 'Hashtable'; use the interface instead
- 🟡 `pmd:ReplaceHashtableWithMap` L140
Consider replacing this Hashtable with the newer java.util.Map
- 🟡 `pmd:LocalVariableCouldBeFinal` L140
Local variable 'h' could be declared final
- 🟡 `pmd:ReplaceHashtableWithMap` L140
Consider replacing this Hashtable with the newer java.util.Map
- 🟡 `pmd:UnusedLocalVariable` L141
Avoid unused local variables such as 'e'.
- 🟡 `pmd:AtLeastOneConstructor` L146
Each class should declare at least one constructor
- 🟡 `pmd:LooseCoupling` L147
Avoid using implementation types like 'Hashtable'; use the interface instead
- 🟡 `pmd:ReplaceHashtableWithMap` L147
Consider replacing this Hashtable with the newer java.util.Map
- 🟡 `pmd:CommentDefaultAccessModifier` L147
Missing commented default access modifier on field 'table'
- 🟡 `pmd:ReplaceHashtableWithMap` L147
Consider replacing this Hashtable with the newer java.util.Map
- 🟡 `pmd:AtLeastOneConstructor` L151
Each class should declare at least one constructor
- 🟡 `pmd:LooseCoupling` L152
Avoid using implementation types like 'Vector'; use the interface instead
- 🟡 `pmd:ReplaceVectorWithList` L152
Consider replacing this Vector with the newer java.util.List
- 🟡 `pmd:CommentDefaultAccessModifier` L152
Missing commented default access modifier on field 'v'
- 🟡 `pmd:ReplaceVectorWithList` L152
Consider replacing this Vector with the newer java.util.List
- 🟡 `pmd:UseArrayListInsteadOfVector` L152
Use ArrayList instead of Vector
- 🟡 `pmd:AtLeastOneConstructor` L156
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L157
Missing commented default access modifier on method 'log()'
- 🟡 `pmd:AtLeastOneConstructor` L164
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L165
Missing commented default access modifier on method 'doIt()'
- 🟡 `pmd:CloseResource` L166
Ensure that resources like this FileInputStream object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L166
Local variable 'fis' could be declared final
- 🟡 `pmd:CloseResource` L167
Ensure that resources like this InputStreamReader object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L167
Local variable 'isr' could be declared final
- 🟡 `pmd:UseStandardCharsets` L167
Please use StandardCharsets constants
- 🟡 `pmd:CloseResource` L168
Ensure that resources like this BufferedReader object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L168
Local variable 'br' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L174
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L175
Missing commented default access modifier on method 'read()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L176
Local variable 'br' could be declared final
- 🟡 `pmd:RelianceOnDefaultCharset` L176
Specify a character set instead of relying on the default charset
- 🟡 `pmd:UseTryWithResources` L177
Consider using a try-with-resources statement instead of explicitly closing the resource
- 🟡 `pmd:AtLeastOneConstructor` L186
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L187
Missing commented default access modifier on method 'accept(String[])'
- 🟡 `pmd:AtLeastOneConstructor` L193
Each class should declare at least one constructor
- 🟡 `pmd:RedundantFieldInitializer` L194
Avoid using redundant field initializer for 'i'
- 🟡 `pmd:CommentDefaultAccessModifier` L194
Missing commented default access modifier on field 'i'
- 🟡 `pmd:CommentDefaultAccessModifier` L195
Missing commented default access modifier on method 'loop()'
- 🟡 `pmd:AssignmentInOperand` L197
Avoid assignment to i in operand
- 🟡 `pmd:AvoidLiteralsInIfCondition` L197
Avoid using literals such as 5 in if statements
- 🟡 `pmd:AtLeastOneConstructor` L205
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L206
Missing commented default access modifier on field 'a'
- 🟡 `pmd:AtLeastOneConstructor` L210
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L211
Missing commented default access modifier on method 'call()'
- 🟡 `pmd:UnnecessaryVarargsArrayCreation` L212
Unnecessary explicit array creation for varargs method call
- 🟡 `pmd:CommentDefaultAccessModifier` L214
Missing commented default access modifier on method 'accept2(String[])'
- 🟡 `pmd:AtLeastOneConstructor` L220
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L221
Public member 'm' declared in a non-public type
- 🟡 `pmd:AtLeastOneConstructor` L226
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L227
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L229
Avoid unused local variables such as 'x'.
- 🟡 `pmd:AvoidPrintStackTrace` L231
Avoid printStackTrace(); use a logger call instead.
- 🟡 `pmd:AtLeastOneConstructor` L237
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L238
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:ExceptionAsFlowControl` L241
Exception thrown at line 240 is caught in this block.
- 🟡 `pmd:AvoidCatchingGenericException` L241
Avoid catching RuntimeException in try-catch block
- 🟡 `pmd:UnusedAssignment` L241
The initial value of exception parameter 'e' is never used (overwritten on line 242)
- 🟡 `pmd:AvoidReassigningCatchVariables` L242
Avoid reassigning caught exception 'e'
- 🟡 `pmd:UnusedAssignment` L242
The value assigned to variable 'e' is never used
- 🟡 `pmd:AtLeastOneConstructor` L248
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L249
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AvoidReassigningLoopVariables` L251
Avoid reassigning the loop control variable 'i'
- 🟡 `pmd:AtLeastOneConstructor` L257
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L258
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:UnusedAssignment` L258
The initial value of parameter 'x' is never used (overwritten on line 259)
- 🟡 `pmd:UnusedAssignment` L259
The value assigned to variable 'x' is never used
- 🟡 `pmd:AtLeastOneConstructor` L264
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L265
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:CloseResource` L267
Ensure that resources like this Statement object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L267
Local variable 'st' could be declared final
- 🟡 `pmd:CloseResource` L268
Ensure that resources like this ResultSet object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L268
Local variable 'rs' could be declared final
- 🟡 `pmd:CheckResultSet` L269
Always check the return of one of the navigation method (next,previous,first,last) of a ResultSet.
- 🟡 `pmd:EmptyCatchBlock` L270
Avoid empty catch blocks
- 🟡 `pmd:AvoidCatchingGenericException` L270
Avoid catching Exception in try-catch block
- 🟡 `pmd:AtLeastOneConstructor` L276
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L277
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L278
Local variable 'c' could be declared final
- 🟡 `pmd:EmptyControlStatement` L279
Empty if statement
- 🟡 `pmd:EnumComparison` L279
Enums should be compared using ==
- 🟡 `pmd:CommentDefaultAccessModifier` L282
Missing commented default access modifier on nested enum 'Color'
- 🟡 `pmd:AtLeastOneConstructor` L286
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L287
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L288
Local variable 'c' could be declared final
- 🟡 `pmd:ExhaustiveSwitchHasDefault` L289
The switch block is exhaustive even without the default case
- 🟡 `pmd:CommentDefaultAccessModifier` L295
Missing commented default access modifier on nested enum 'Color'
- 🟡 `pmd:AtLeastOneConstructor` L299
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L300
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:EmptyControlStatement` L301
Empty for statement
- 🟡 `pmd:ForLoopVariableCount` L301
Too many control variables in the for statement
- 🟡 `pmd:UnusedAssignment` L301
The updated value of variable 'j' is never used
- 🟡 `pmd:AtLeastOneConstructor` L307
Each class should declare at least one constructor
- 🟡 `pmd:AvoidFieldNameMatchingMethodName` L308
Field LOG has the same name as a method
- 🟡 `pmd:CommentDefaultAccessModifier` L309
Missing commented default access modifier on method 'log(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L309
Parameter 'msg' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L315
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L316
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L316
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L317
Empty if statement
- 🟡 `pmd:LiteralsFirstInComparisons` L317
Position literals first in String comparisons
- 🟡 `pmd:AtLeastOneConstructor` L323
Each class should declare at least one constructor
- 🟡 `pmd:MissingOverride` L324
The method 'toString()' is missing an @Override annotation.
- 🟡 `pmd:OverrideBothEqualsAndHashcode` L327
Ensure you override both equals() and hashCode()
- 🟡 `pmd:MissingOverride` L327
The method 'equals(Object)' is missing an @Override annotation.
- 🟡 `pmd:AtLeastOneConstructor` L331
Each class should declare at least one constructor
- 🟡 `pmd:MissingOverride` L332
The method 'toString()' is missing an @Override annotation.
- 🟡 `pmd:AtLeastOneConstructor` L336
Each class should declare at least one constructor
- 🟡 `pmd:OverrideBothEqualsAndHashcode` L337
Ensure you override both equals() and hashCode()
- 🟡 `pmd:MissingOverride` L337
The method 'equals(Object)' is missing an @Override annotation.
- 🟡 `pmd:AtLeastOneConstructor` L343
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L344
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L345
Local variable 'c' could be declared final
- 🟡 `pmd:TooFewBranchesForSwitch` L346
A switch with less than three branches is inefficient, use a if statement instead.
- 🟡 `pmd:NonExhaustiveSwitch` L346
Switch statements or expressions should be exhaustive, add a default case (or missing enum branches)
- 🟡 `pmd:CommentDefaultAccessModifier` L350
Missing commented default access modifier on nested enum 'Color2'
- 🟡 `pmd:AtLeastOneConstructor` L354
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L355
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:ExceptionAsFlowControl` L358
Exception thrown at line 357 is caught in this block.
- 🟡 `pmd:PreserveStackTrace` L359
Thrown exception does not preserve the stack trace of exception 'e' on all code paths
- 🟡 `pmd:AtLeastOneConstructor` L365
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L366
Missing commented default access modifier on field 'i'
- 🟡 `pmd:PrimitiveWrapperInstantiation` L366
Do not use `new Integer(...)`, prefer `Integer.valueOf(...)`
- 🟡 `pmd:UnnecessaryBoxing` L366
Unnecessary explicit boxing
- 🟡 `pmd:AtLeastOneConstructor` L370
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L371
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L372
Local variable 'x' could be declared final
- 🟡 `pmd:TooFewBranchesForSwitch` L373
A switch with less than three branches is inefficient, use a if statement instead.
- 🟡 `pmd:DefaultLabelNotLastInSwitch` L374
The default label should be the last label in a switch statement or expression
- 🟡 `pmd:AtLeastOneConstructor` L381
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L382
Missing commented default access modifier on method 'bad(List<String>)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L382
Parameter 'l' is not assigned and could be declared final
- 🟡 `pmd:ForLoopCanBeForeach` L383
This for loop can be replaced by a foreach loop
- 🟡 `pmd:AtLeastOneConstructor` L390
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L391
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:AtLeastOneConstructor` L397
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L398
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLabel` L399
Avoid unused labels such as 'label'.
- 🟡 `pmd:AtLeastOneConstructor` L407
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L408
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L409
Avoid unused local variables such as 'x'.
- 🟡 `pmd:AtLeastOneConstructor` L415
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateField` L416
Avoid unused private fields such as 'secret'.
- 🟡 `pmd:PublicMemberInNonPublicType` L417
Public member 'm' declared in a non-public type
- 🟡 `pmd:AtLeastOneConstructor` L422
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateMethod` L423
Avoid unused private methods such as 'helper()'.
- 🟡 `pmd:PublicMemberInNonPublicType` L425
Public member 'm' declared in a non-public type
- 🟡 `pmd:AtLeastOneConstructor` L430
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L431
Missing commented default access modifier on method 'bad(List<String>)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L431
Parameter 'l' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L432
Empty if statement
- 🟡 `pmd:UseCollectionIsEmpty` L432
Substitute calls to size() == 0 (or size() != 0, size() > 0, size() < 1) with calls to isEmpty()
- 🟡 `pmd:AtLeastOneConstructor` L438
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L439
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LooseCoupling` L440
Avoid using implementation types like 'HashSet'; use the interface instead
- 🟡 `pmd:UnusedLocalVariable` L440
Avoid unused local variables such as 'set'.
- 🟡 `pmd:UseEnumCollections` L440
This collection could be an EnumSet
- 🟡 `pmd:LooseCoupling` L441
Avoid using implementation types like 'HashMap'; use the interface instead
- 🟡 `pmd:UnusedLocalVariable` L441
Avoid unused local variables such as 'map'.
- 🟡 `pmd:UseEnumCollections` L441
This collection could be an EnumMap
- 🟡 `pmd:CommentDefaultAccessModifier` L443
Missing commented default access modifier on nested enum 'Color'
- 🟡 `pmd:AtLeastOneConstructor` L457
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L460
Missing commented default access modifier on method 'debug(String, String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L460
Parameter 'param1' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L460
Parameter 'param2' is not assigned and could be declared final
- 🟡 `pmd:LabeledStatement` L471
Avoid using labeled statements such as 'lbl2'.
- 🟡 `pmd:AvoidLiteralsInIfCondition` L472
Avoid using literals such as 3 in if statements
- 🟡 `pmd:UnusedLabel` L476
Avoid unused labels such as 'lbl3'.
- 🟡 `pmd:AvoidLiteralsInIfCondition` L477
Avoid using literals such as 4 in if statements
- 🟡 `pmd:AtLeastOneConstructor` L487
Each class should declare at least one constructor
- 🟡 `pmd:ReplaceEnumerationWithIterator` L487
Consider replacing this Enumeration with the newer java.util.Iterator
- 🟡 `pmd:RedundantFieldInitializer` L488
Avoid using redundant field initializer for 'i'
- 🟡 `pmd:MissingOverride` L490
The method 'hasMoreElements()' is missing an @Override annotation.
- 🟡 `pmd:MissingOverride` L494
The method 'nextElement()' is missing an @Override annotation.
- 🟡 `pmd:AssignmentInOperand` L495
Avoid assignment to i in operand
- 🟡 `pmd:AtLeastOneConstructor` L500
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L506
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateMethod` L507
Avoid unused private methods such as 'bar(String)'.
- 🟡 `pmd:UnusedFormalParameter` L507
Avoid unused method parameters such as 'howdy'.
- 🟡 `pmd:AtLeastOneConstructor` L513
Each class should declare at least one constructor
- 🟡 `pmd:NonStaticInitializer` L514
Non-static initializers are confusing
- 🟡 `pmd:EmptyControlStatement` L515
Empty do..while statement
- 🟡 `pmd:WhileLoopWithLiteralBoolean` L517
The loop can be simplified.
- 🟡 `pmd:UnnecessaryWarningSuppression` L531
Unnecessary PMD suppression comment
- 🟡 `pmd:AtLeastOneConstructor` L532
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L548
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L549
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:AvoidDollarSigns` L554
Avoid using dollar signs in variable/method/class/interface names
- 🟡 `pmd:AtLeastOneConstructor` L554
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L558
Each class should declare at least one constructor
- 🟡 `pmd:AvoidProtectedFieldInFinalClass` L559
Avoid protected fields in a final class. Change to private or package access.
- 🟡 `pmd:AtLeastOneConstructor` L563
Each class should declare at least one constructor
- 🟡 `pmd:AvoidProtectedMethodInFinalClassNotExtending` L564
Avoid protected methods in a final class that doesnt extend anything other than Object. Change to private or package access.
- 🟡 `pmd:AtLeastOneConstructor` L569
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L570
Missing commented default access modifier on method 'jni()'
- 🟡 `pmd:AtLeastOneConstructor` L574
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L575
Missing commented default access modifier on field 'flag'
- 🟡 `pmd:CommentDefaultAccessModifier` L576
Missing commented default access modifier on method 'getFlag()'
- 🟡 `pmd:AtLeastOneConstructor` L582
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L586
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L587
Missing commented default access modifier on field 'x'
- 🟡 `pmd:CommentDefaultAccessModifier` L588
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:AtLeastOneConstructor` L593
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L594
Missing commented default access modifier on method 'bad(boolean)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L594
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:ConfusingTernary` L595
Avoid if (x != y) ..; else ..;
- 🟡 `pmd:SimplifyBooleanReturns` L595
This if statement can be replaced by `return {condition};`
- 🟡 `pmd:OnlyOneReturn` L596
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:AtLeastOneConstructor` L604
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L605
Missing commented default access modifier on method 'bad(boolean)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L605
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:ControlStatementBraces` L607
This statement should have braces
- 🟡 `pmd:AtLeastOneConstructor` L612
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L613
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L613
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L614
Empty if statement
- 🟡 `pmd:AtLeastOneConstructor` L620
Each class should declare at least one constructor
- 🟡 `pmd:AbstractClassWithoutAbstractMethod` L620
This abstract class does not have any abstract methods
- 🟡 `pmd:CommentDefaultAccessModifier` L621
Missing commented default access modifier on method 'empty()'
- 🟡 `pmd:AtLeastOneConstructor` L626
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L630
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateField` L631
Avoid unused private fields such as 'late'.
- 🟡 `pmd:CommentDefaultAccessModifier` L632
Missing commented default access modifier on method 'method()'
- 🟡 `pmd:AtLeastOneConstructor` L637
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateField` L638
Avoid unused private fields such as 'bad_name'.
- 🟡 `pmd:AtLeastOneConstructor` L642
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L643
Missing commented default access modifier on method 'doIt(int)'
- 🟡 `pmd:AtLeastOneConstructor` L647
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L648
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:ForLoopShouldBeWhileLoop` L650
This for loop could be simplified to a while loop
- 🟡 `pmd:AtLeastOneConstructor` L657
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L658
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:AtLeastOneConstructor` L663
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L664
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L666
Avoid unused local variables such as 'x'.
- 🟡 `pmd:IdenticalCatchBranches` L669
'catch' branch identical to 'ArithmeticException' branch
- 🟡 `pmd:AvoidCatchingGenericException` L669
Avoid catching Exception in try-catch block
- 🟡 `pmd:AtLeastOneConstructor` L676
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L677
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L678
Avoid unused local variables such as 'f'.
- 🟡 `pmd:LambdaCanBeMethodReference` L678
Lambda expression could be written as a method reference: `String::length`
- 🟡 `pmd:AtLeastOneConstructor` L683
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L684
Missing commented default access modifier on method 'isReady(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L684
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L690
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L691
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L692
Local variable 'x' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L698
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L699
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L700
Local variable 'bad_var' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L706
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L707
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L707
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L713
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L714
Missing commented default access modifier on method 'BadMethod()'
- 🟡 `pmd:AtLeastOneConstructor` L719
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L720
Public member 'm' declared in a non-public type
- 🟡 `pmd:UnusedPrivateField` L722
Avoid unused private fields such as 'x'.
- 🟡 `pmd:FieldDeclarationsShouldBeAtStartOfClass` L722
Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
- 🟡 `pmd:FinalFieldCouldBeStatic` L722
The final field x could be made static
- 🟡 `pmd:AtLeastOneConstructor` L726
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L727
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L727
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:OnlyOneReturn` L729
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:AtLeastOneConstructor` L736
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L737
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L738
Local variable 'x' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L746
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L747
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:AtLeastOneConstructor` L753
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L757
Each class should declare at least one constructor
- 🟡 `pmd:UnnecessaryAnnotationValueElement` L758
Avoid the use of value in annotations when its the only element
- 🟡 `pmd:CommentDefaultAccessModifier` L759
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:AtLeastOneConstructor` L764
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L765
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:UnnecessaryBlock` L766
This block isn't necessary.
- 🟡 `pmd:UnusedLocalVariable` L767
Avoid unused local variables such as 'x'.
- 🟡 `pmd:AtLeastOneConstructor` L773
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L774
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:UnusedLocalVariable` L775
Avoid unused local variables such as 'i'.
- 🟡 `pmd:PrimitiveWrapperInstantiation` L775
Do not use `new Integer(...)`, prefer `Integer.valueOf(...)`
- 🟡 `pmd:UnnecessaryBoxing` L775
Unnecessary explicit boxing
- 🟡 `pmd:AtLeastOneConstructor` L780
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L781
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L782
Local variable 'o' could be declared final
- 🟡 `pmd:UnusedLocalVariable` L783
Avoid unused local variables such as 's'.
- 🟡 `pmd:UnnecessaryConstructor` L789
Avoid unnecessary constructors - the compiler will generate these for you
- 🟡 `pmd:CommentDefaultAccessModifier` L789
Missing commented default access modifier on constructor 'UnNeedCons()'
- 🟡 `pmd:AtLeastOneConstructor` L794
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L795
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:UnusedLocalVariable` L796
Avoid unused local variables such as 's'.
- 🟡 `pmd:UnnecessaryModifier` L806
Unnecessary modifiers 'public abstract' on method 'm': the method is declared in an interface type
- 🟡 `pmd:AtLeastOneConstructor` L810
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L811
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:UnnecessaryReturn` L813
Unnecessary return statement
- 🟡 `pmd:AtLeastOneConstructor` L818
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L819
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L820
Local variable 'x' could be declared final
- 🟡 `pmd:UnnecessarySemicolon` L820
Unnecessary semicolon
- 🟡 `pmd:AtLeastOneConstructor` L826
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L827
Missing commented default access modifier on field 'l'
- 🟡 `pmd:UseDiamondOperator` L827
Explicit type arguments can be replaced by a diamond: `new ArrayList<>()`
- 🟡 `pmd:AtLeastOneConstructor` L831
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L832
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L833
Local variable 'x' could be declared final
- 🟡 `pmd:UseExplicitTypes` L833
Use Explicit Types
- 🟡 `pmd:AtLeastOneConstructor` L839
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L840
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L841
Local variable 'x' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L847
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L848
Missing commented default access modifier on field 'x'
- 🟡 `pmd:CommentDefaultAccessModifier` L849
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L850
Local variable 'y' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L856
Each class should declare at least one constructor
- 🟡 `pmd:UseShortArrayInitializer` L857
Array initialization can be written shorter
- 🟡 `pmd:CommentDefaultAccessModifier` L857
Missing commented default access modifier on field 'a'
- 🟡 `pmd:AtLeastOneConstructor` L861
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L862
Missing commented default access modifier on field 'x'
- 🟡 `pmd:UseUnderscoresInNumericLiterals` L862
Number 1000000 should separate every third digit with an underscore
- 🟡 `pmd:AtLeastOneConstructor` L866
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L867
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L868
Local variable 'len' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L874
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L875
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L876
Local variable 'x' could be declared final
- 🟡 `pmd:UnnecessaryConstructor` L898
Avoid unnecessary constructors - the compiler will generate these for you
- 🟡 `pmd:CommentDefaultAccessModifier` L898
Missing commented default access modifier on constructor 'ParentFix()'
- 🟡 `pmd:UnnecessaryConstructor` L902
Avoid unnecessary constructors - the compiler will generate these for you
- 🟡 `pmd:CommentDefaultAccessModifier` L902
Missing commented default access modifier on constructor 'ChildFix()'
- 🟡 `pmd:AtLeastOneConstructor` L908
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L909
Public member 'getLength' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L909
Parameter 'strings' is not assigned and could be declared final
- 🟡 `pmd:PrematureDeclaration` L910
Declaration of 'length' can be moved closer to its usages
- 🟡 `pmd:OnlyOneReturn` L912
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:LocalVariableCouldBeFinal` L914
Local variable 'str' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L922
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L923
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:UnusedAssignment` L924
The initializer for variable 'o' is never used (overwritten on line 925)
- 🟡 `pmd:UnnecessaryCast` L925
Unnecessary cast (Object)
- 🟡 `pmd:AtLeastOneConstructor` L935
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L939
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L940
Missing commented default access modifier on field 'otherFoo'
- 🟡 `pmd:UselessQualifiedThis` L940
Useless qualified this usage in the same class.
- 🟡 `pmd:CommentDefaultAccessModifier` L941
Missing commented default access modifier on method 'doSomething()'
- 🟡 `pmd:UselessQualifiedThis` L942
Useless qualified this usage in the same class.
- 🟡 `pmd:AtLeastOneConstructor` L948
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L949
Public member 'lengthSum' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L949
Parameter 'strings' is not assigned and could be declared final
- 🟡 `pmd:LocalVariableCouldBeFinal` L955
Local variable 'str' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L963
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L964
Public member 'compute' declared in a non-public type
- 🟡 `pmd:AtLeastOneConstructor` L968
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L969
Missing commented default access modifier on field 'count'
- 🟡 `pmd:CommentDefaultAccessModifier` L971
Missing commented default access modifier on method 'isEnabled()'
- 🟡 `pmd:CommentDefaultAccessModifier` L975
Missing commented default access modifier on method 'getCount()'
- 🟡 `pmd:CommentDefaultAccessModifier` L979
Missing commented default access modifier on method 'computeSomething()'
- 🟡 `pmd:AtLeastOneConstructor` L995
Each class should declare at least one constructor
- 🟡 `pmd:LinguisticNaming` L996
Linguistics Antipattern - The field 'isReady' indicates linguistically it is a boolean, but it is 'int'
- 🟡 `pmd:CommentDefaultAccessModifier` L996
Missing commented default access modifier on field 'isReady'
- 🟡 `pmd:LinguisticNaming` L998
Linguistics Antipattern - The method 'isValid' indicates linguistically it returns a boolean, but it returns 'int'
- 🟡 `pmd:CommentDefaultAccessModifier` L998
Missing commented default access modifier on method 'isValid()'
- 🟡 `pmd:AtLeastOneConstructor` L1004
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1005
Public member 'invalid' declared in a non-public type
- 🟡 `pmd:UnnecessaryConstructor` L1012
Avoid unnecessary constructors - the compiler will generate these for you
- 🟡 `pmd:CommentDefaultAccessModifier` L1012
Missing commented default access modifier on constructor 'ParentRemain()'
- 🟡 `pmd:UnnecessaryConstructor` L1016
Avoid unnecessary constructors - the compiler will generate these for you
- 🟡 `pmd:CallSuperInConstructor` L1016
It is a good practice to call super() in a constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1016
Missing commented default access modifier on constructor 'ChildRemain()'
- 🟡 `pmd:AtLeastOneConstructor` L1022
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1023
Public member 'lengthSum' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L1023
Parameter 'strings' is not assigned and could be declared final
- 🟡 `pmd:VariableDeclarationUsageDistance` L1024
Distance between declaration of 'length' and its first usage is 11, current threshold is 7
- 🟡 `pmd:LocalVariableCouldBeFinal` L1035
Local variable 'str' could be declared final
- 🔵 `pmd:UnnecessaryImport` L14
Unused import 'java.nio.charset.StandardCharsets'
- 🔵 `pmd:UnnecessaryImport` L17
Unused import 'java.util.Date'
- 🔵 `pmd:UnnecessaryImport` L22
Unused import 'java.util.Iterator'
- 🔵 `pmd:UnnecessaryImport` L30
Unused static import 'java.lang.Math.min'
- 🔵 `pmd:UnnecessaryImport` L31
Unused static import 'java.lang.Math.abs'
- 🔵 `pmd:UnnecessaryImport` L32
Unused static import 'java.lang.Math.sqrt'
- 🔵 `pmd:UnnecessaryImport` L33
Unused static import 'java.lang.Math.pow'
- 🔵 `pmd:UnnecessaryImport` L34
Unused static import 'java.lang.Math.floor'
- 🔵 `pmd:UnnecessaryImport` L35
Unused static import 'java.lang.Math.ceil'
- 🔵 `pmd:UnnecessaryImport` L36
Unused static import 'java.lang.Math.round'
- 🔵 `pmd:UnnecessaryImport` L37
Unused static import 'java.lang.Math.random'
- 🔵 `pmd:UnnecessaryImport` L38
Unused static import 'java.lang.Math.sin'
- 🔵 `pmd:UnnecessaryImport` L39
Unused static import 'java.lang.Math.cos'
- 🔵 `pmd:UnnecessaryImport` L40
Unused static import 'java.lang.Math.tan'
- 🔵 `pmd:UseVarargs` L59
Consider using varargs for methods or constructors which take an array the last parameter.
- 🔵 `pmd:UseVarargs` L187
Consider using varargs for methods or constructors which take an array the last parameter.
- 🔵 `pmd:OneDeclarationPerLine` L206
Use one line for each declaration, it enhances code readability.
- 🔵 `pmd:UnnecessaryFullyQualifiedName` L487
Unnecessary qualifier 'java.util': 'Enumeration' is already in scope because it is imported in this file
- 🔵 `pmd:BooleanGetMethodName` L576
A getX() method which returns a boolean or Boolean should be named isX()
- 🔵 `pmd:ExtendsObject` L626
No need to explicitly extend Object.
- 🔵 `pmd:TypeParameterNamingConventions` L753
The type parameter name 'bad' doesn't match '[A-Z]'
- 🔵 `pmd:UnnecessaryFullyQualifiedName` L796
Unnecessary qualifier 'java.lang': 'String' is already in scope because it is declared in java.lang
- 🔵 `pmd:UnnecessaryFullyQualifiedName` L796
Unnecessary qualifier 'java.lang': 'String' is already in scope because it is declared in java.lang
- 🔵 `pmd:UselessParentheses` L841
Useless parentheses around `1 + 2`.
- 🔵 `pmd:UseVarargs` L909
Consider using varargs for methods or constructors which take an array the last parameter.
- 🔵 `pmd:UnnecessaryInterfaceDeclaration` L935
Unnecessary interface declaration 'com.demo.bpcs.IBase', already provided by 'com.demo.bpcs.IExt'.
- 🔵 `pmd:UseVarargs` L949
Consider using varargs for methods or constructors which take an array the last parameter.
- 🔵 `pmd:UseVarargs` L1023
Consider using varargs for methods or constructors which take an array the last parameter.
AI 审查 · 7 条建议
- 🔴 [AI] [bug] `null-statement-dereference` L268
**RsDemo 中 Statement 为 null 却直接调用 executeQuery,必然触发 NullPointerException**
L267 将 Statement 变量 st 初始化为 nullL268 立即调用 st.executeQuery("select 1"),在没有任何赋值的情况下必然抛出 NullPointerException。静态分析只报告了资源未关闭和 ResultSet 返回值未检查,但未识别这个必然的空指针。
建议: 先通过 Connection.createStatement() 正确初始化 Statement,或在调用前判空并处理;也可直接使用 try-with-resources 管理 Statement 与 ResultSet。
- 🟡 [AI] [bug] `incomplete-object-initialization` L71
**Hasher 构造函数吞掉 MessageDigest 初始化异常,对象处于不一致状态**
Hasher 构造函数在 catch(Exception) 中仅记录日志,MessageDigest.getInstance("SHA-256") 失败时 digest 保持为 null。对象仍会被创建并返回给调用方,后续任何使用 digest 的操作都会触发 NullPointerException。应 fail-fast,让对象在构造失败时不可用。
建议: 将 digest 声明为 final,构造函数改为初始化失败时抛出 IllegalStateException(携带原始异常),或使用静态初始化块并在失败时抛出 ExceptionInInitializerError。
- 🟡 [AI] [security] `hardcoded-ip-address` L93
**NetConfig 中硬编码了 IP 地址,存在安全风险**
L93 的 host 字段硬编码了内网 IP "192.168.1.1"。硬编码 IP 会使代码难以在不同环境部署,且易被攻击者直接定位内网地址;若该值被提交到源码仓库,可能成为信息泄露点。静态分析结果未包含 AvoidUsingHardCodedIP 规则。
建议: 将主机地址改为从配置、环境变量或系统属性读取,并在启动时校验格式。
- 🟡 [AI] [bug] `resource-leak-on-construction-failure` L176
**链式构造缓冲读取器时,若中间构造失败将泄漏底层 FileInputStream**
L176 使用 new BufferedReader(new InputStreamReader(new FileInputStream("h.txt"))) 链式构造资源。若 InputStreamReader 或 BufferedReader 的构造函数抛出异常,已经成功打开的 FileInputStream 不会被关闭,因为此时还没有引用指向它。静态分析报告了 CloseResource 和 UseTryWithResources,但未指出链式构造本身是泄漏点。
建议: 使用 Files.newBufferedReader(Paths.get("h.txt"), StandardCharsets.UTF_8) 一步创建,或先用独立变量创建 FileInputStream 并放入 try-with-resources。
- 🟡 [AI] [bug] `infinite-iteration` L490
**EnumerationImpl 的 hasMoreElements() 永远返回 true,造成无限迭代**
EnumerationImpl 的 hasMoreElements() 恒为 true,而 nextElement() 每次使 i 自增并返回新字符串,导致枚举序列无限增长,最终 i 会溢出为负数。此外类声明使用了裸类型 java.util.Enumeration,未指定泛型参数,存在类型安全隐患。
建议: 为 hasMoreElements() 设置明确的终止条件(如 i < 10),并为 Enumeration 指定泛型参数(如 Enumeration<String>),同时让 nextElement() 返回 String 类型。
- 🔵 [AI] [style] `redundant-local-variable` L868
**InlineVar 中局部变量 len 仅使用一次,可直接内联**
L868 声明的 int len = 5 只在 L869 使用一次,没有复用价值,属于冗余局部变量,增加阅读负担。静态分析未对 InlineVar 报告 VariableCanBeInlined。
建议: 删除 len 变量,直接将字面量 5 传给 System.out.println。
- 🔵 [AI] [design] `misleading-getter` L975
**getCount() 返回 computeSomething() 而非 count 字段,getter 语义误导**
L975 的 getCount() 方法名为获取 count 字段的 getter,实际却返回 computeSomething() 的计算结果(42)。调用方会误以为获取的是对象状态 count,但实际拿到的与字段无关,容易引入逻辑错误。静态分析仅报告了 L996/L998 的 LinguisticNaming,未覆盖此方法。
建议: 让 getCount() 返回 count 字段,或将方法重命名为 computeCount()/getComputedValue() 以准确表达语义。
@@ -0,0 +1,46 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\CallSuperDemo.java`
**语言:** java
**耗时:** 104.2s
**分析工具:** pmd
---
总计: 10 | 错误: 3 | 警告: 7 | 建议: 0
静态分析 · 7 个问题
- 🔴 `pmd:SystemPrintln` L34
使用了System.out/err
建议: 在Android中应使用日志框架,例如用 android.util.Log.d("CallSuperMain", "demo call super") 替代 System.out.println,并确保导入 Log 类。
- 🟡 `pmd:AtLeastOneConstructor` L11
每个类应至少声明一个构造函数
建议: 为类添加一个无参构造函数,并调用 super()。例如:public MissingSuperFirst() { super(); }
- 🟡 `pmd:CallSuperFirst` L13
应在方法开头调用super
建议: 在onCreate方法的第一行调用 super.onCreate(bundle),然后再执行其他操作。
- 🟡 `pmd:CommentDefaultAccessModifier` L17
方法'foo()'缺少默认访问修饰符的注释
建议: 为默认包私有访问权限添加注释,例如:/* default */ void foo();或者如果方法仅在类内部使用,可以显式声明为 private。
- 🟡 `pmd:AtLeastOneConstructor` L22
每个类应至少声明一个构造函数
建议: 为类添加一个无参构造函数,并调用 super()。例如:public MissingSuperLast() { super(); }
- 🟡 `pmd:CallSuperLast` L24
应在方法末尾调用super
建议: 在onPause方法的最后一行调用 super.onPause(),确保父类生命周期逻辑正确执行。
- 🟡 `pmd:CommentDefaultAccessModifier` L28
方法'foo()'缺少默认访问修饰符的注释
建议: 为默认包私有访问权限添加注释,例如:/* default */ void foo();或者如果方法仅在类内部使用,可以显式声明为 private。
AI 审查 · 3 条建议
- 🔴 [AI] [bug] `activity-class-not-public` L11
**Activity子类未声明为public**
在Android中,Activity类必须声明为public,否则系统可能无法通过反射实例化并启动。MissingSuperFirst类当前为包私有,应在类声明中添加public修饰符。
- 🔴 [AI] [bug] `activity-class-not-public` L22
**Activity子类未声明为public**
MissingSuperLast类同样应声明为public,确保系统能够实例化。
- 🟡 [AI] [design] `no-useless-main` L33
**包含无用的main方法**
CallSuperMain类中的main方法在Android应用中不会作为入口执行,Android应用由Activity生命周期驱动。此方法可能是遗留代码或用于本地测试,建议删除或将其抽取到独立的测试类中使用JUnit进行测试。
+72
View File
@@ -0,0 +1,72 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\jsp\DemoJsp.jsp`
**语言:** html
**耗时:** 239.9s
**分析工具:** jsp
---
总计: 17 | 错误: 6 | 警告: 10 | 建议: 1
静态分析 · 12 个问题
- 🔴 `eslint:no-unused-vars` L18
第 18 行:'init' 已定义但从未使用。
建议: 若该函数用于页面初始化,应显式绑定 window.addEventListener('load', init); 否则删除整个 init 函数。
- 🔴 `eslint:no-var` L19
第 19 行:不允许使用 var,请改用 let 或 const。
建议: x 声明后未再被赋值,应使用 const x = 1; 代替 var x = 1;。
- 🔴 `eslint:no-undef` L20
第 20 行:'alert' 未定义。
建议: 在浏览器环境应使用 window.alert(x); 更明确;也可以添加 /* global alert */ 注释作为全局声明。
- 🔴 `pmd:NoClassAttribute` L37
第 37 行:不要使用名为 class 的属性。
建议: 将 class="highlight" 改为 id="highlight"(并确保页面内 id 唯一),在外部 CSS 中使用 #highlight 定义样式。
- 🟡 `pmd:NoScriptlets` L11
第 11 行:JSP 文件中应避免使用 scriptlet(Java 脚本片段)。
建议: 将脚本片段改为 JSTL/EL 表达式,例如输出“Hello <c:out value="${param.name}"/>”,业务逻辑应放在控制器或后台 Bean 中;并记得声明 JSTL taglib。
- 🟡 `pmd:LocalVariableCouldBeFinal` L12
第 12 行:局部变量 'name' 可声明为 final。
建议: 将 String name 改为 final String name = request.getParameter("name"); 更推荐移除 scriptlet,使用 <c:out value="${param.name}"/> 输出。
- 🟡 `pmd:NoInlineScript` L17
第 17 行:不要将 JavaScript 内容内联在 JSP/HTML 中。
建议: 将脚本移到独立的 .js 文件,例如 src="js/init.js",然后通过 <script src="js/init.js"></script> 引入;不要使用内联 script 块。
- 🟡 `pmd:NoInlineStyleInformation` L25
第 25 行:避免在 JSP 文件中包含样式信息(<p align="center">)。
建议: 移除 align 属性,改用外部 CSS,例如 <p id="center-aligned">,并在 CSS 中定义 #center-aligned { text-align: center; }。
- 🟡 `pmd:NoInlineStyleInformation` L25
第 25 行:避免在 JSP 文件中包含样式信息(<b> 加粗标签)。
建议: 用语义化的 <strong>Bold inline style</strong> 代替 <b>,或使用 CSS font-weight 设置加粗。
- 🟡 `pmd:NoInlineStyleInformation` L25
第 25 行:避免在 JSP 文件中包含样式信息(<font color="red">)。
建议: 将颜色样式移到外部 CSS,例如改为 <span id="font-inline-style-demo">Font inline style</span>,并在 CSS 中定义 #font-inline-style-demo { color: red; }。
- 🟡 `pmd:DontNestJsfInJstlIteration` L33
第 33 行:不要在会遍历 body 的 JSTL 迭代标签内嵌套 JSF 组件。
建议: 若迁移到 Facelets,使用 <ui:repeat value="#{items}" var="item"> 替代 c:forEach;否则请避免在 JSP 中混用 JSF 组件与 JSTL 迭代生命周期。
- 🟡 `pmd:DuplicateJspImports` L42
第 42 行:java.util.List 被重复导入。
建议: 删除其中一个重复的 <%@ page import="java.util.List" %>,只保留一条导入语句。
AI 审查 · 5 条建议
- 🔴 [AI] [security] `reflected-xss` L13
**反射型 XSS:用户参数未编码直接输出**
request.getParameter("name") 由用户控制,脚本中通过 out.println("Hello " + name) 直接拼入 HTML;当 name 含 <script>alert(document.cookie)</script> 等载荷时会被浏览器执行。
建议: 移除 scriptlet,改用 <c:out value="${param.name}"/> 或 OWASP Java Encoder 对输出做 HTML 实体编码,杜绝 XSS。
- 🔴 [AI] [bug] `missing-taglib-declaration` L32
**缺少 JSTL/JSF 标签库声明**
页面第 32-33 行使用了 <c:forEach> 与 <h:outputText>,但没有任何 <%@ taglib %> 指令声明 c 和 h 前缀;JSP 容器无法解析这些标签,会导致编译失败或运行时错误。
建议: 在页面顶部增加 JSTL Core 和 JSF HTML 标签库的 taglib 指令,命名空间 URI 根据实际 JSTL/JSF 版本调整。
- 🟡 [AI] [style] `inline-style-attribute` L26
**第 26 行存在未标记的内联样式属性**
<div style="color: red;"> 将样式写在 JSP 页面中,虽然 PMD 结果只标记了第 25 行的样式,但第 26 行同样违反内联样式外置的原则,也会增加维护成本。
建议: 移除 style 属性,将颜色样式写到外部 CSS 文件,例如 <div id="inline-style-demo">Inline style</div>,并在 CSS 中定义 #inline-style-demo { color: red; }。
- 🟡 [AI] [bug] `jsf-el-value-expression` L33
**JSF 组件值表达式应使用 #{} 而不是 ${}**
第 33 行 <h:outputText value="${item}"/> 在 JSF 组件中使用了 JSP EL ${}。JSF 的 ValueExpression 应使用 #{} 延迟求值,否则可能被当作普通字符串/文本解析,或无法正确解析 c:forEach 暴露的变量。
建议: 改为 <h:outputText value="#{item}"/>;若配合修复 DontNestJsfInJstlIteration,把外层 c:forEach 替换为 Facelets 的 ui:repeat。
- 🔵 [AI] [design] `incomplete-html5-document` L5
**HTML5 文档缺少 DOCTYPE 与 lang 属性**
<html> 没有前置 <!DOCTYPE html>,也没有 lang 属性,可能导致浏览器以怪癖模式渲染,同时影响屏幕阅读器/SEO 对页面语言的识别。
建议: 在 <html> 前添加 <!DOCTYPE html>,并设置 <html lang="zh-CN">(按实际内容语言调整)。
@@ -0,0 +1,1707 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\designep\DesignErrorProne.java`
**语言:** java
**耗时:** 195.1s
**分析工具:** pmd
---
总计: 771 | 错误: 166 | 警告: 598 | 建议: 7
静态分析 · 762 个问题
- 🔴 `pmd:AbstractClassWithoutAnyMethod` L30
抽象类没有抽象方法,abstract 可能只是用来阻止实例化
建议: 如果目的是阻止实例化,应使用私有或 protected 构造函数而非 abstract。
- 🔴 `pmd:SystemPrintln` L39
使用了 System.out/err 输出
建议: 改用 SLF4J/Log4j 等日志框架记录输出。
- 🔴 `pmd:AvoidThrowingNullPointerException` L75
避免手动抛出 NullPointerException
建议: 应通过参数校验、Objects.requireNonNull 等方式处理,而不是直接 new NullPointerException。
- 🔴 `pmd:AvoidThrowingRawExceptionTypes` L82
避免抛出原始异常类型 RuntimeException
建议: 抛出自定义异常或更具体的异常类型,并携带业务上下文。
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L93
只有私有构造函数,应声明为 final
建议: 给类添加 final 修饰符,防止通过反射或内部类扩展。
- 🔴 `pmd:SystemPrintln` L103
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L140
Usage of System.out/err
- 🔴 `pmd:FieldNamingConventions` L149
字段命名不符合约定
建议: 按 Java 命名规范:常量用 UPPER_SNAKE,普通字段用 lowerCamel。
- 🔴 `pmd:SystemPrintln` L155
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L158
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L161
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L164
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L167
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L170
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L173
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L176
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L179
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L182
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L185
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L188
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L191
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L194
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L197
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L200
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L203
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L206
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L209
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L212
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L215
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L218
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L221
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L224
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L227
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L230
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L233
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L236
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L239
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L242
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L245
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L248
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L251
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L254
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L257
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L260
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L263
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L266
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L269
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L272
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L275
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L278
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L281
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L284
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L287
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L290
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L293
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L296
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L299
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L302
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L422
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L423
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L424
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L425
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L426
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L427
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L428
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L429
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L430
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L431
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L432
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L433
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L436
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L437
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L438
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L439
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L440
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L441
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L442
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L443
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L444
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L445
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L446
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L447
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L450
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L451
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L452
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L453
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L454
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L455
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L456
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L457
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L458
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L459
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L460
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L461
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L464
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L495
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L496
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L497
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L498
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L501
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L502
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L503
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L504
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L507
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L508
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L509
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L510
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L513
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L514
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L515
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L516
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L528
Usage of System.out/err
- 🔴 `pmd:AvoidReassigningParameters` L538
避免重新为参数赋值
建议: 使用新的局部变量保存修改后的值。
- 🔴 `pmd:SystemPrintln` L539
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L577
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L578
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L586
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L597
Usage of System.out/err
- 🔴 `pmd:ConstructorCallsOverridableMethod` L693
构造函数中调用了可重写方法
建议: 避免在构造期间调用非 final/method,或将该方法设为 final/private。
- 🔴 `pmd:DoNotCallGarbageCollectionExplicitly` L702
不要显式触发垃圾回收
建议: 删除 System.gc(),交由 JVM 自动管理内存。
- 🔴 `pmd:AvoidThrowingRawExceptionTypes` L728
Avoid throwing raw exception type RuntimeException.
- 🔴 `pmd:EqualsNull` L758
避免使用 equals() 与 null 比较
建议: 使用 o == null 判空,而不是 o.equals(null)。
- 🔴 `pmd:AvoidReassigningParameters` L766
Avoid reassigning parameters such as 's'
- 🔴 `pmd:SystemPrintln` L768
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L788
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L790
Usage of System.out/err
- 🔴 `pmd:MethodNamingConventions` L816
方法命名不符合约定
建议: 使用 lowerCamelCase 命名方法,如 sameName()。
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L829
This class has only private constructors and may be final
- 🔴 `pmd:MoreThanOneLogger` L835
类中包含多个 logger
建议: 统一使用一个 logger 实例,避免日志输出混乱。
- 🔴 `pmd:SystemPrintln` L843
Usage of System.out/err
- 🔴 `pmd:ReturnEmptyCollectionRatherThanNull` L882
应返回空集合而不是 null
建议: 返回 Collections.emptyList() 或 List.of()。
- 🔴 `pmd:SuspiciousEqualsMethodName` L909
方法名与 equals(Object) 高度相似,容易误导
建议: 重命名方法,或改为真正重写 equals(Object)。
- 🔴 `pmd:SystemPrintln` L928
Usage of System.out/err
- 🔴 `pmd:FieldNamingConventions` L996
The field name 'TypeName' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:SingleMethodSingleton` L1029
类包含多个 getInstance 方法,单例模式混乱
建议: 只保留一个无参 getInstance(),移除重载方法。
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L1029
This class has only private constructors and may be final
- 🔴 `pmd:SingletonClassReturningNewInstance` L1039
getInstance 总是创建新对象,不符合单例行为
建议: getInstance 应返回缓存的唯一实例,而不是新建对象。
- 🔴 `pmd:SystemPrintln` L1070
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1078
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1089
Usage of System.out/err
- 🔴 `pmd:FieldNamingConventions` L1096
The constant name '_LOG' doesn't match '[A-Z][A-Z_0-9]*'
- 🔴 `pmd:GuardLogStatement` L1101
日志调用应使用日志级别守卫包裹
建议: 添加 if (LOGGER.isDebugEnabled()) 等守卫,或使用占位符避免字符串拼接。
- 🔴 `pmd:SystemPrintln` L1134
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1178
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1208
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L1218
Usage of System.out/err
- 🔴 `pmd:AvoidBranchingStatementAsLastInLoop` L1222
避免在循环末尾使用 break/continue 作为最后一条语句
建议: 调整循环结构,使正常退出条件更明确。
- 🔴 `pmd:AvoidMultipleUnaryOperators` L1230
多个一元运算符叠用可能造成误解或 bug
建议: 简化表达式,只保留一个运算符或使用括号明确语义。
- 🔴 `pmd:AvoidMultipleUnaryOperators` L1231
Using multiple unary operators may be a bug, and/or is confusing.
- 🔴 `pmd:SystemPrintln` L1232
Usage of System.out/err
- 🔴 `pmd:BrokenNullCheck` L1239
null 检查逻辑有误,可能导致 NullPointerException 或逻辑错误
建议: 检查短路语义:判空应使用 && 或 || 正确组合,并在空值分支避免解引用。
- 🔴 `pmd:BrokenNullCheck` L1242
Dereferencing the qualifier of this expression will throw a NullPointerException
- 🔴 `pmd:ProperCloneImplementation` L1254
clone() 应通过 super.clone() 实现
建议: 使用 super.clone() 并强制转换返回类型,而不是 new 新对象。
- 🔴 `pmd:ProperCloneImplementation` L1286
Object clone() should be implemented with super.clone()
- 🔴 `pmd:FieldNamingConventions` L1339
The field name 'LOG' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:FieldNamingConventions` L1344
The constant name '_LOG' doesn't match '[A-Z][A-Z_0-9]*'
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L1372
This class has only private constructors and may be final
- 🔴 `pmd:FieldNamingConventions` L1373
The static field name 'INSTANCE' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:ClassWithOnlyPrivateConstructorsShouldBeFinal` L1384
This class has only private constructors and may be final
- 🔴 `pmd:FieldNamingConventions` L1385
The static field name 'INSTANCE' doesn't match '[a-z][a-zA-Z0-9]*'
- 🔴 `pmd:SystemPrintln` L1400
Usage of System.out/err
- 🟡 `pmd:AtLeastOneConstructor` L30
每个类应至少声明一个构造函数(适用于所有命中项)
建议: 为没有构造函数的类添加显式构造函数;若类不应被实例化,则改为私有构造。
- 🟡 `pmd:AbstractClassWithoutAbstractMethod` L30
该抽象类没有任何抽象方法
建议: 删除 abstract 关键字,或为类增加抽象方法。
- 🟡 `pmd:AtLeastOneConstructor` L34
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L35
缺少默认访问修饰符的注释(方法/字段/类)
建议: 为包级私有成员添加 /* default */ 注释,或显式声明 private/protected/public。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L35
参数未被赋值,可以声明为 final(适用于所有命中项)
建议: 在方法参数前添加 final 修饰符,避免无意中重新赋值。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L35
Parameter 'b' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L35
Parameter 'c' is not assigned and could be declared final
- 🟡 `pmd:CollapsibleIfStatements` L37
该 if 语句可以与父级 if 合并
建议: 使用 && 或 || 将嵌套条件合并,减少嵌套层级。
- 🟡 `pmd:AvoidDeeplyNestedIfStmts` L38
if 嵌套过深,难以阅读
建议: 使用卫语句、提前返回或提取方法降低嵌套深度。
- 🟡 `pmd:CollapsibleIfStatements` L38
This if statement could be combined with its parent
- 🟡 `pmd:AtLeastOneConstructor` L47
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L48
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AvoidRethrowingException` L51
捕获异常后仅重新抛出,应避免
建议: 不要捕获该异常,直接在方法签名中声明抛出;若必须捕获,请加入实际处理逻辑。
- 🟡 `pmd:CommentDefaultAccessModifier` L55
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:AtLeastOneConstructor` L60
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L61
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:CommentDefaultAccessModifier` L68
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:AtLeastOneConstructor` L73
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L74
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AtLeastOneConstructor` L80
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L81
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AtLeastOneConstructor` L87
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L88
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AvoidUncheckedExceptionsInSignatures` L88
方法/构造函数不应显式声明非受检异常 RuntimeException
建议: 从 throws 子句中删除非受检异常。
- 🟡 `pmd:MissingStaticMethodInNonInstantiatableClass` L93
类无法实例化,且没有提供任何静态方法或字段
建议: 添加 public static 方法/工厂方法,或将类声明为 final 并仅作工具类使用。
- 🟡 `pmd:AtLeastOneConstructor` L99
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L100
Missing commented default access modifier on method 'bad(int, int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L100
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L100
Parameter 'b' is not assigned and could be declared final
- 🟡 `pmd:CollapsibleIfStatements` L102
This if statement could be combined with its parent
- 🟡 `pmd:AtLeastOneConstructor` L110
Each class should declare at least one constructor
- 🟡 `pmd:DataClass` L110
类疑似数据类(只包含 getter/setter
建议: 将数据与行为封装在一起,增加业务方法,避免仅作为数据容器。
- 🟡 `pmd:PublicMemberInNonPublicType` L113
非公共类型中声明了公共成员
建议: 将类改为 public,或将该成员的访问级别降为 package 私有。
- 🟡 `pmd:PublicMemberInNonPublicType` L116
Public member 'setName' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L116
Parameter 'name' is not assigned and could be declared final
- 🟡 `pmd:PublicMemberInNonPublicType` L119
Public member 'getAge' declared in a non-public type
- 🟡 `pmd:PublicMemberInNonPublicType` L122
Public member 'setAge' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L122
Parameter 'age' is not assigned and could be declared final
- 🟡 `pmd:MissingSerialVersionUID` L128
实现 Serializable 的类应定义 serialVersionUID
建议: 添加 private static final long serialVersionUID = 1L;
- 🟡 `pmd:AtLeastOneConstructor` L128
Each class should declare at least one constructor
- 🟡 `pmd:DoNotExtendJavaLangError` L128
异常不应继承 java.lang.Error
建议: 应继承 Exception/RuntimeExceptionError 留给 JVM 内部严重错误。
- 🟡 `pmd:AtLeastOneConstructor` L132
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L133
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedAssignment` L134
变量的初始值从未被使用
建议: 删除初始赋值,或直接使用最终需要的值初始化。
- 🟡 `pmd:CommentDefaultAccessModifier` L142
Missing commented default access modifier on method 'check()'
- 🟡 `pmd:AtLeastOneConstructor` L148
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L149
Missing commented default access modifier on field 'CONST'
- 🟡 `pmd:FinalFieldCouldBeStatic` L149
final 字段可以声明为 static
建议: 若字段是编译时常量,请声明为 static final。
- 🟡 `pmd:AtLeastOneConstructor` L153
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L154
Missing commented default access modifier on method 'm1(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L154
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L157
Missing commented default access modifier on method 'm2(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L157
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L160
Missing commented default access modifier on method 'm3(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L160
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L163
Missing commented default access modifier on method 'm4(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L163
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L166
Missing commented default access modifier on method 'm5(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L166
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L169
Missing commented default access modifier on method 'm6(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L169
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L172
Missing commented default access modifier on method 'm7(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L172
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L175
Missing commented default access modifier on method 'm8(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L175
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L178
Missing commented default access modifier on method 'm9(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L178
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L181
Missing commented default access modifier on method 'm10(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L181
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L184
Missing commented default access modifier on method 'm11(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L184
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L187
Missing commented default access modifier on method 'm12(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L187
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L190
Missing commented default access modifier on method 'm13(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L190
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L193
Missing commented default access modifier on method 'm14(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L193
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L196
Missing commented default access modifier on method 'm15(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L196
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L199
Missing commented default access modifier on method 'm16(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L199
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L202
Missing commented default access modifier on method 'm17(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L202
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L205
Missing commented default access modifier on method 'm18(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L205
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L208
Missing commented default access modifier on method 'm19(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L208
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L211
Missing commented default access modifier on method 'm20(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L211
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L214
Missing commented default access modifier on method 'm21(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L214
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L217
Missing commented default access modifier on method 'm22(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L217
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L220
Missing commented default access modifier on method 'm23(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L220
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L223
Missing commented default access modifier on method 'm24(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L223
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L226
Missing commented default access modifier on method 'm25(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L226
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L229
Missing commented default access modifier on method 'm26(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L229
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L232
Missing commented default access modifier on method 'm27(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L232
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L235
Missing commented default access modifier on method 'm28(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L235
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L238
Missing commented default access modifier on method 'm29(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L238
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L241
Missing commented default access modifier on method 'm30(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L241
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L244
Missing commented default access modifier on method 'm31(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L244
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L247
Missing commented default access modifier on method 'm32(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L247
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L250
Missing commented default access modifier on method 'm33(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L250
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L253
Missing commented default access modifier on method 'm34(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L253
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L256
Missing commented default access modifier on method 'm35(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L256
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L259
Missing commented default access modifier on method 'm36(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L259
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L262
Missing commented default access modifier on method 'm37(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L262
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L265
Missing commented default access modifier on method 'm38(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L265
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L268
Missing commented default access modifier on method 'm39(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L268
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L271
Missing commented default access modifier on method 'm40(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L271
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L274
Missing commented default access modifier on method 'm41(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L274
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L277
Missing commented default access modifier on method 'm42(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L277
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L280
Missing commented default access modifier on method 'm43(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L280
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L283
Missing commented default access modifier on method 'm44(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L283
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L286
Missing commented default access modifier on method 'm45(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L286
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L289
Missing commented default access modifier on method 'm46(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L289
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L292
Missing commented default access modifier on method 'm47(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L292
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L295
Missing commented default access modifier on method 'm48(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L295
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L298
Missing commented default access modifier on method 'm49(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L298
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:CommentDefaultAccessModifier` L301
Missing commented default access modifier on method 'm50(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L301
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:UnusedPrivateField` L308
存在未使用的私有字段
建议: 删除该字段,或确认其确实被需要后补充使用。
- 🟡 `pmd:ImmutableField` L308
字段可以声明为 final
建议: 初始化后不再变更的字段应添加 final 修饰符。
- 🟡 `pmd:UnnecessaryConstructor` L310
构造函数不必要,编译器会生成默认构造
建议: 删除空的、无实际逻辑的构造函数。
- 🟡 `pmd:CommentDefaultAccessModifier` L310
Missing commented default access modifier on constructor 'Immut()'
- 🟡 `pmd:AtLeastOneConstructor` L315
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L317
Public member 'getname' declared in a non-public type
- 🟡 `pmd:PublicMemberInNonPublicType` L320
Public member 'setname' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L320
Parameter 'n' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L326
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L327
Missing commented default access modifier on method 'bad(A)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L327
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:LawOfDemeter` L328
Call to `getB` on foreign value `a` (degree 1)
- 🟡 `pmd:AtLeastOneConstructor` L330
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L330
Missing commented default access modifier on nested class 'A'
- 🟡 `pmd:CommentDefaultAccessModifier` L331
Missing commented default access modifier on method 'getB()'
- 🟡 `pmd:AtLeastOneConstructor` L335
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L335
Missing commented default access modifier on nested class 'B'
- 🟡 `pmd:CommentDefaultAccessModifier` L336
Missing commented default access modifier on method 'getC()'
- 🟡 `pmd:AtLeastOneConstructor` L340
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L340
Missing commented default access modifier on nested class 'C'
- 🟡 `pmd:CommentDefaultAccessModifier` L341
Missing commented default access modifier on method 'doIt()'
- 🟡 `pmd:AtLeastOneConstructor` L347
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L348
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L348
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:SimplifyBooleanReturns` L349
该 if 语句可被替换为返回条件表达式
建议: 例如 if (x) return true; else return false 应改为 return x;
- 🟡 `pmd:LogicInversion` L349
Use opposite operator instead of the logic complement operator.
- 🟡 `pmd:OnlyOneReturn` L350
方法应只有唯一出口,且应在最后一条语句
建议: 将多个 return 改为单出口风格,或使用表达式结果返回。
- 🟡 `pmd:UseUtilityClass` L359
所有成员都是静态的,应添加私有构造防止实例化
建议: 为工具类添加 private 无参构造函数,并将类声明为 final。
- 🟡 `pmd:MutableStaticState` L360
不要使用非 final 非私有的静态字段
建议: 改为 private static final,或通过 getter/setter 控制访问。
- 🟡 `pmd:CommentDefaultAccessModifier` L360
Missing commented default access modifier on field 'counter'
- 🟡 `pmd:AtLeastOneConstructor` L364
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L365
Public member 'x' declared in a non-public type
- 🟡 `pmd:AtLeastOneConstructor` L369
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L370
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:SignatureDeclareThrowsException` L370
方法/构造函数不应显式抛出 java.lang.Exception
建议: 抛出具体异常类型,避免宽泛的 Exception。
- 🟡 `pmd:AtLeastOneConstructor` L375
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L376
Missing commented default access modifier on method 'bad(boolean)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L376
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:SimplifiedTernary` L377
三元表达式可以简化
建议: 例如 return x ? true : false 应改为 return x。
- 🟡 `pmd:AtLeastOneConstructor` L382
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L383
Missing commented default access modifier on method 'bad(boolean)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L383
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:SimplifyBooleanExpressions` L384
布尔表达式包含不必要的比较
建议: 例如 return x == true 应改为 return x。
- 🟡 `pmd:AtLeastOneConstructor` L389
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L390
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L390
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:SimplifyBooleanReturns` L391
This if statement can be replaced by `return {condition};`
- 🟡 `pmd:OnlyOneReturn` L392
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:AtLeastOneConstructor` L400
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L401
Missing commented default access modifier on method 'bar(Object)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L401
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L402
存在空的控制语句(if/for/while 等)
建议: 补充逻辑或删除空语句块。
- 🟡 `pmd:SimplifyConditional` L402
instanceof 前不需要检查 null
建议: 删除 x != null &&,因为 x instanceof List 已覆盖 null 情况。
- 🟡 `pmd:AtLeastOneConstructor` L408
Each class should declare at least one constructor
- 🟡 `pmd:SingularField` L409
字段可能应改为局部变量
建议: 如果字段只在一个方法中使用,请改为方法内局部变量。
- 🟡 `pmd:PublicMemberInNonPublicType` L411
Public member 'foo' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L411
Parameter 'y' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L418
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L419
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L419
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:SwitchDensity` L420
switch 中语句与分支比例过高
建议: 将每个 case 的逻辑抽取为独立方法,或使用多态/映射表重构。
- 🟡 `pmd:AtLeastOneConstructor` L471
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L472
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:AtLeastOneConstructor` L475
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L477
Missing commented default access modifier on method 'm()'
- 🟡 `pmd:UselessOverridingMethod` L477
重写方法仅调用 super,无实际用途
建议: 删除该重写方法,让父类方法直接生效。
- 🟡 `pmd:UseUtilityClass` L483
All members are static. Consider adding a private no-args constructor to prevent instantiation.
- 🟡 `pmd:CommentDefaultAccessModifier` L484
Missing commented default access modifier on method 'helper()'
- 🟡 `pmd:AtLeastOneConstructor` L491
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L492
Public member 'bar' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L492
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L525
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L526
Missing commented default access modifier on method 'bar(Object, String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L526
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L526
Parameter 'baz' is not assigned and could be declared final
- 🟡 `pmd:MisplacedNullCheck` L527
null 检查位置错误,可能引发 NullPointerException
建议: 先判空再调用方法,例如 a != null && a.equals(baz)。
- 🟡 `pmd:AtLeastOneConstructor` L536
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L537
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:AssignmentInOperand` L538
避免在操作数中赋值
建议: 将赋值移到表达式外,单独一行,再参与判断。
- 🟡 `pmd:UseUtilityClass` L545
All members are static. Consider adding a private no-args constructor to prevent instantiation.
- 🟡 `pmd:MutableStaticState` L546
Do not use non-final non-private static fields
- 🟡 `pmd:CommentDefaultAccessModifier` L546
Missing commented default access modifier on field 'counter'
- 🟡 `pmd:CommentDefaultAccessModifier` L548
Missing commented default access modifier on constructor 'AssignStatic()'
- 🟡 `pmd:AssignmentToNonFinalStatic` L549
构造函数中给非 final 静态字段赋值可能不安全
建议: 使用实例字段,或通过 static final/初始化块管理静态状态。
- 🟡 `pmd:AtLeastOneConstructor` L554
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L555
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:SignatureDeclareThrowsException` L555
A method/constructor should not explicitly throw java.lang.Exception
- 🟡 `pmd:LocalVariableCouldBeFinal` L556
局部变量可声明为 final
建议: 为只赋值一次的局部变量添加 final 修饰符。
- 🟡 `pmd:AvoidAccessibilityAlteration` L557
不应使用 setAccessible(true) 修改可见性
建议: 避免反射破坏封装;若必须,应评估安全风险并限制调用权限。
- 🟡 `pmd:AtLeastOneConstructor` L562
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L563
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L564
Local variable 'o' could be declared final
- 🟡 `pmd:AvoidCallingFinalize` L565
避免显式调用 finalize() 方法
建议: 删除显式调用,改用 try-with-resources 或 Cleaner 管理资源。
- 🟡 `pmd:AtLeastOneConstructor` L570
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L571
Missing commented default access modifier on field 'd'
- 🟡 `pmd:AvoidDecimalLiteralsInBigDecimalConstructor` L571
避免用浮点字面量构造 BigDecimal,可能产生精度问题
建议: 使用字符串构造:new BigDecimal("0.1")。
- 🟡 `pmd:AtLeastOneConstructor` L575
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L576
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AtLeastOneConstructor` L583
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L584
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L584
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:AvoidLiteralsInIfCondition` L585
if 条件中避免使用魔术数字/字面量
建议: 将 42、5 等常量提取为命名常量。
- 🟡 `pmd:AtLeastOneConstructor` L592
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L593
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AssignmentInOperand` L596
Avoid assignment to x in operand
- 🟡 `pmd:AtLeastOneConstructor` L602
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L603
Missing commented default access modifier on field 'x'
- 🟡 `pmd:AvoidUsingOctalValues` L603
避免使用八进制字面量
建议: 去掉前导 0,或明确使用 0x/0b 前缀。
- 🟡 `pmd:AtLeastOneConstructor` L607
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L608
Missing commented default access modifier on method 'bad(Object, Object)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L608
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L608
Parameter 'b' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L609
Empty if statement
- 🟡 `pmd:AtLeastOneConstructor` L615
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L616
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UselessPureMethodCall` L618
调用了纯方法但未使用结果
建议: 删除该调用,或将结果赋给变量并使用。
- 🟡 `pmd:CommentDefaultAccessModifier` L620
Missing commented default access modifier on method 'doSomething()'
- 🟡 `pmd:AtLeastOneConstructor` L625
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L626
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UselessPureMethodCall` L627
Do not call pure method toString if the result is not used.
- 🟡 `pmd:CommentDefaultAccessModifier` L630
Missing commented default access modifier on method 'doSomething()'
- 🟡 `pmd:AtLeastOneConstructor` L635
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L636
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:CloseResource` L637
资源使用后应关闭
建议: 使用 try-with-resources 自动关闭 InputStream 等资源。
- 🟡 `pmd:LocalVariableCouldBeFinal` L637
Local variable 'in' could be declared final
- 🟡 `pmd:CheckSkipResult` L638
应检查 InputStream.skip() 的返回值
建议: 将 skip 返回值赋给变量,并判断是否满足所需跳过字节数。
- 🟡 `pmd:AtLeastOneConstructor` L643
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L644
Missing commented default access modifier on method 'bad(Collection<String>)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L644
Parameter 'c' is not assigned and could be declared final
- 🟡 `pmd:UnusedLocalVariable` L645
存在未使用的局部变量
建议: 删除未使用的局部变量,或补全其使用逻辑。
- 🟡 `pmd:ClassCastExceptionWithToArray` L645
Collection.toArray() 的使用会抛出 ClassCastException
建议: 使用 c.toArray(new String[0]) 传入类型化数组。
- 🟡 `pmd:AtLeastOneConstructor` L650
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L651
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L652
Local variable 'in' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L658
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L659
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L660
Avoid unused local variables such as 'l'.
- 🟡 `pmd:UnusedLocalVariable` L661
Avoid unused local variables such as 'o'.
- 🟡 `pmd:PrimitiveWrapperInstantiation` L661
不要使用 new Integer(...),应使用 Integer.valueOf(...)
建议: 使用装箱缓存或 Integer.valueOf 替代 new Integer。
- 🟡 `pmd:UnnecessaryBoxing` L661
存在不必要的显式装箱
建议: 直接使用基本类型或依赖自动装箱。
- 🟡 `pmd:AtLeastOneConstructor` L666
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L667
Missing commented default access modifier on method 'bad(String, String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L667
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L667
Parameter 'b' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L668
Empty if statement
- 🟡 `pmd:CompareObjectsWithEquals` L668
比较对象引用应使用 equals() 而不是 ==
建议: 对非基本类型对象比较使用 equals()。
- 🟡 `pmd:UseEqualsToCompareStrings` L668
比较字符串应使用 equals() 而不是 ==
建议: 使用 a.equals(b),并按需调用 equalsIgnoreCase。
- 🟡 `pmd:AtLeastOneConstructor` L674
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L675
Missing commented default access modifier on method 'bad(double)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L675
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L676
Empty if statement
- 🟡 `pmd:ComparisonWithNaN` L676
与 NaN 比较恒为 false
建议: 使用 Double.isNaN(x) 判断 NaN。
- 🟡 `pmd:AtLeastOneConstructor` L682
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L683
Missing commented default access modifier on method 'call()'
- 🟡 `pmd:CommentDefaultAccessModifier` L686
Missing commented default access modifier on method 'accept(String[])'
- 🟡 `pmd:CommentDefaultAccessModifier` L692
Missing commented default access modifier on constructor 'CtorCall()'
- 🟡 `pmd:CommentDefaultAccessModifier` L695
Missing commented default access modifier on method 'overridable()'
- 🟡 `pmd:AtLeastOneConstructor` L700
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L701
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:MissingSerialVersionUID` L707
Classes implementing Serializable should set a serialVersionUID
- 🟡 `pmd:AtLeastOneConstructor` L707
Each class should declare at least one constructor
- 🟡 `pmd:DoNotExtendJavaLangThrowable` L707
异常不应直接继承 java.lang.Throwable
建议: 应继承 Exception 或 RuntimeException。
- 🟡 `pmd:AtLeastOneConstructor` L711
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L712
Missing commented default access modifier on field 'path'
- 🟡 `pmd:DoNotHardCodeSDCard` L712
不要硬编码 /sdcard 路径
建议: 使用环境变量或上下文 API 获取存储路径。
- 🟡 `pmd:AtLeastOneConstructor` L716
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L717
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:DoNotTerminateVM` L718
不应调用 System.exit() 终止 JVM
建议: 通过受控方式结束应用,或抛出异常交给上层处理。
- 🟡 `pmd:AtLeastOneConstructor` L723
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L724
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:CommentDefaultAccessModifier` L731
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:AtLeastOneConstructor` L736
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L737
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:DontUseFloatTypeForLoopIndices` L738
不要使用浮点类型作为循环索引,浮点精度可能导致循环异常
建议: 改用 int/long 循环变量,或使用 double 并明确终止条件。
- 🟡 `pmd:EmptyControlStatement` L738
Empty for statement
- 🟡 `pmd:AtLeastOneConstructor` L744
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L745
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:EmptyCatchBlock` L748
避免空 catch 块
建议: 至少记录日志或做降级处理,不要静默吞掉异常。
- 🟡 `pmd:AvoidCatchingGenericException` L748
避免捕获泛化 Exception
建议: 捕获具体异常类型,如 IOException、IllegalArgumentException。
- 🟡 `pmd:CommentDefaultAccessModifier` L751
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:AtLeastOneConstructor` L756
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L757
Missing commented default access modifier on method 'bad(Object)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L757
Parameter 'o' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L758
Empty if statement
- 🟡 `pmd:AtLeastOneConstructor` L764
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L765
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:AtLeastOneConstructor` L773
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L774
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L774
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:IdenticalConditionalBranches` L775
条件分支完全相同,条件判断无意义
建议: 删除 if/else,直接返回相同结果或提取公共逻辑。
- 🟡 `pmd:OnlyOneReturn` L776
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:AtLeastOneConstructor` L784
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L785
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L785
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:ImplicitSwitchFallThrough` L789
switch 分支存在隐式 fall-through
建议: 在 case 末尾补上 break/return,或添加注释明确故意 fall-through。
- 🟡 `pmd:AtLeastOneConstructor` L799
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L800
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L801
Avoid unused local variables such as 'c'.
- 🟡 `pmd:PrimitiveWrapperInstantiation` L801
Do not use `new Integer(...)`, prefer `Integer.valueOf(...)`
- 🟡 `pmd:AtLeastOneConstructor` L806
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L807
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:ForLoopVariableCount` L808
for 循环中控制变量过多
建议: 拆分循环或将额外变量移到循环外,保持循环头简洁。
- 🟡 `pmd:AvoidReassigningLoopVariables` L809
避免修改循环控制变量
建议: 不要在循环体内或内层循环更新外层循环变量,使用独立变量。
- 🟡 `pmd:AtLeastOneConstructor` L815
Each class should declare at least one constructor
- 🟡 `pmd:MethodWithSameNameAsEnclosingClass` L816
方法与包含它的类同名(可能误当构造函数)
建议: 重命名方法,避免与类名混淆。
- 🟡 `pmd:CommentDefaultAccessModifier` L816
Missing commented default access modifier on method 'SameName()'
- 🟡 `pmd:AtLeastOneConstructor` L821
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L822
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L822
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L823
Empty if statement
- 🟡 `pmd:MissingStaticMethodInNonInstantiatableClass` L829
Class cannot be instantiated and does not provide any static methods or fields
- 🟡 `pmd:UnusedPrivateField` L836
Avoid unused private fields such as 'LOG1'.
- 🟡 `pmd:UnusedPrivateField` L837
Avoid unused private fields such as 'LOG2'.
- 🟡 `pmd:AtLeastOneConstructor` L841
Each class should declare at least one constructor
- 🟡 `pmd:NonStaticInitializer` L842
非静态初始化器令人困惑
建议: 将初始化逻辑移到构造函数或工厂方法中。
- 🟡 `pmd:AtLeastOneConstructor` L848
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L849
Missing commented default access modifier on field 's'
- 🟡 `pmd:CommentDefaultAccessModifier` L850
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:NullAssignment` L851
将对象赋值为 null 是代码坏味道
建议: 用 Optional 或空集合/空对象模式替代 null 赋值。
- 🟡 `pmd:AtLeastOneConstructor` L856
Each class should declare at least one constructor
- 🟡 `pmd:OverrideBothEqualsAndHashcode` L857
重写 equals() 时应同时重写 hashCode()
建议: 为相等的对象保证 hashCode 一致,避免集合类行为异常。
- 🟡 `pmd:MissingOverride` L857
重写方法缺少 @Override 注解
建议: 在继承或实现的方法上添加 @Override 注解。
- 🟡 `pmd:AtLeastOneConstructor` L863
Each class should declare at least one constructor
- 🟡 `pmd:MissingOverride` L864
The method 'compareTo(CmpOnly)' is missing an @Override annotation.
- 🟡 `pmd:OverrideBothEqualsAndHashCodeOnComparable` L864
实现 Comparable 时应同时重写 equals() 和 hashCode()
建议: 保持 compareTo、equals、hashCode 三者语义一致。
- 🟡 `pmd:AtLeastOneConstructor` L870
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L871
Missing commented default access modifier on field 'c'
- 🟡 `pmd:ReplaceJavaUtilCalendar` L871
应使用 java.time 替代 java.util.Calendar
建议: 使用 LocalDate/LocalDateTime/ZonedDateTime 等新时间 API。
- 🟡 `pmd:AtLeastOneConstructor` L875
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L876
Missing commented default access modifier on field 'd'
- 🟡 `pmd:ReplaceJavaUtilDate` L876
应使用 java.time 替代 java.util.Date
建议: 使用 Instant/LocalDateTime 并配合 DateTimeFormatter 处理格式。
- 🟡 `pmd:ReplaceJavaUtilDate` L876
Usage of java.util.Date should be replaced with classes from java.time
- 🟡 `pmd:AtLeastOneConstructor` L880
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L881
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AtLeastOneConstructor` L887
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L888
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:OnlyOneReturn` L890
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:ReturnFromFinallyBlock` L892
避免在 finally 块中返回值
建议: 从 try/catch 中返回结果,finally 只做资源清理。
- 🟡 `pmd:AtLeastOneConstructor` L898
Each class should declare at least one constructor
- 🟡 `pmd:AvoidFieldNameMatchingTypeName` L899
字段名与类名相同容易混淆
建议: 重命名字段,例如 sdf 改为 dateFormat。
- 🟡 `pmd:CommentDefaultAccessModifier` L899
Missing commented default access modifier on field 'sdf'
- 🟡 `pmd:SimpleDateFormatNeedsLocale` L899
SimpleDateFormat 实例化时应指定 Locale
建议: new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT)。
- 🟡 `pmd:AtLeastOneConstructor` L903
Each class should declare at least one constructor
- 🟡 `pmd:AvoidStringBufferField` L904
StringBuffer 字段可能造成内存问题
建议: 优先使用 StringBuilder,并避免在长生命周期对象中持有大缓冲区。
- 🟡 `pmd:CommentDefaultAccessModifier` L904
Missing commented default access modifier on field 'sb'
- 🟡 `pmd:AtLeastOneConstructor` L908
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L909
Missing commented default access modifier on method 'equals(String)'
- 🟡 `pmd:AtLeastOneConstructor` L914
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L915
Missing commented default access modifier on method 'hashcode()'
- 🟡 `pmd:AtLeastOneConstructor` L920
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L921
Missing commented default access modifier on field 's'
- 🟡 `pmd:AtLeastOneConstructor` L925
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L926
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnconditionalIfStatement` L927
不要使用恒真/恒假的 if 语句
建议: 删除无条件 if,直接执行其中的代码或删除整个语句块。
- 🟡 `pmd:AtLeastOneConstructor` L934
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L935
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L935
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L936
Empty if statement
- 🟡 `pmd:AtLeastOneConstructor` L942
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L943
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L943
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:UnusedLocalVariable` L944
Avoid unused local variables such as 's'.
- 🟡 `pmd:UnnecessaryConversionTemporary` L944
避免不必要的临时转换对象
建议: 使用 String.valueOf(x) 替代 new Integer(x).toString()。
- 🟡 `pmd:PrimitiveWrapperInstantiation` L944
Do not use `new Integer(...)`, prefer `Integer.valueOf(...)`
- 🟡 `pmd:AtLeastOneConstructor` L949
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L950
Missing commented default access modifier on field 's'
- 🟡 `pmd:OverrideBothEqualsAndHashcode` L951
Ensure you override both equals() and hashCode()
- 🟡 `pmd:MissingOverride` L951
The method 'equals(Object)' is missing an @Override annotation.
- 🟡 `pmd:MethodArgumentCouldBeFinal` L951
Parameter 'o' is not assigned and could be declared final
- 🟡 `pmd:EmptyControlStatement` L952
Empty if statement
- 🟡 `pmd:AtLeastOneConstructor` L959
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L960
Missing commented default access modifier on method 'bad(String, String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L960
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L960
Parameter 'b' is not assigned and could be declared final
- 🟡 `pmd:CompareObjectsWithEquals` L961
Use equals() to compare object references.
- 🟡 `pmd:UseEqualsToCompareStrings` L961
Use equals() to compare strings instead of '==' or '!='
- 🟡 `pmd:AtLeastOneConstructor` L966
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L967
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UselessPureMethodCall` L968
Do not call pure method length if the result is not used.
- 🟡 `pmd:AtLeastOneConstructor` L973
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L974
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L974
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:UselessPureMethodCall` L975
Do not call pure method toUpperCase if the result is not used.
- 🟡 `pmd:UseLocaleWithCaseConversions` L975
toUpperCase()/toLowerCase() 应指定 Locale
建议: 使用 s.toUpperCase(Locale.ROOT) 或指定业务 locale。
- 🟡 `pmd:AtLeastOneConstructor` L980
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L981
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L982
Avoid unused local variables such as 'cl'.
- 🟡 `pmd:UseProperClassLoader` L982
getClassLoader() 在 J2EE 中可能不符合预期
建议: 使用 Thread.currentThread().getContextClassLoader()。
- 🟡 `pmd:AtLeastOneConstructor` L987
Each class should declare at least one constructor
- 🟡 `pmd:AvoidFieldNameMatchingMethodName` L988
字段名与同名方法容易混淆
建议: 重命名字段或方法,避免同名歧义。
- 🟡 `pmd:CommentDefaultAccessModifier` L988
Missing commented default access modifier on field 'value'
- 🟡 `pmd:CommentDefaultAccessModifier` L990
Missing commented default access modifier on method 'value()'
- 🟡 `pmd:AtLeastOneConstructor` L995
Each class should declare at least one constructor
- 🟡 `pmd:AvoidFieldNameMatchingTypeName` L996
It is somewhat confusing to have a field name matching the declaring class name
- 🟡 `pmd:CommentDefaultAccessModifier` L996
Missing commented default access modifier on field 'TypeName'
- 🟡 `pmd:AtLeastOneConstructor` L1000
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1001
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AvoidCatchingGenericException` L1004
Avoid catching Exception in try-catch block
- 🟡 `pmd:EmptyControlStatement` L1005
Empty if statement
- 🟡 `pmd:AvoidInstanceofChecksInCatchClause` L1005
catch 块中不应使用 instanceof 判断异常类型
建议: 为每种异常类型增加独立的 catch 子句。
- 🟡 `pmd:CommentDefaultAccessModifier` L1009
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:AtLeastOneConstructor` L1014
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1015
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L1016
Local variable 'x' could be declared final
- 🟡 `pmd:TooFewBranchesForSwitch` L1017
switch 分支少于三个,使用 if 更高效
建议: 将 switch 改为 if/else if 判断。
- 🟡 `pmd:NonExhaustiveSwitch` L1017
switch 不完整,应包含 default 或所有枚举分支
建议: 补充 default 分支处理未知情况。
- 🟡 `pmd:NonCaseLabelInSwitch` L1020
switch 中出现了非 case 标签
建议: 移除标签,或重构 switch 逻辑。
- 🟡 `pmd:UnusedLabel` L1020
存在未使用的标签
建议: 删除未引用标签,避免误导。
- 🟡 `pmd:PublicMemberInNonPublicType` L1035
Public member 'getInstance' declared in a non-public type
- 🟡 `pmd:PublicMemberInNonPublicType` L1039
Public member 'getInstance' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L1039
Parameter 'obj' is not assigned and could be declared final
- 🟡 `pmd:VariableCanBeInlined` L1040
局部变量可以内联,不需要额外存储
建议: 直接返回值或表达式,减少中间变量。
- 🟡 `pmd:LocalVariableCouldBeFinal` L1040
Local variable 's' could be declared final
- 🟡 `pmd:SignatureDeclareThrowsException` L1047
A method/constructor should not explicitly throw java.lang.Exception
- 🟡 `pmd:UnsupportedJdkApiUsage` L1048
使用了不受支持的 JDK API(如 sun.misc.Unsafe
建议: 改用标准 JDK API,例如 VarHandle/Atomic 类或通过受支持方式获取 Unsafe。
- 🟡 `pmd:AtLeastOneConstructor` L1053
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1054
Missing commented default access modifier on method 'bar()'
- 🟡 `pmd:IdempotentOperations` L1056
存在幂等操作(如变量赋值给自身/重复转换)
建议: 删除重复或自我赋值,保留一次有效操作。
- 🟡 `pmd:UnusedAssignment` L1056
The value assigned to variable 'x' is never used
- 🟡 `pmd:AtLeastOneConstructor` L1061
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1062
Public member 'hashcode' declared in a non-public type
- 🟡 `pmd:SuspiciousHashcodeMethodName` L1062
方法名与 hashCode() 高度相似,但签名不符
建议: 重命名为 hashcode -> hashCode,并返回 int 且加上 @Override
- 🟡 `pmd:AtLeastOneConstructor` L1068
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1069
Missing commented default access modifier on method 'foo()'
- 🟡 `pmd:SuspiciousOctalEscape` L1070
字符串中的八进制转义后紧跟数字字符很可疑
建议: 将转义拆分或改用 Unicode 转义,避免歧义。
- 🟡 `pmd:AtLeastOneConstructor` L1075
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1076
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L1076
Parameter 'buz' is not assigned and could be declared final
- 🟡 `pmd:LocalVariableCouldBeFinal` L1077
Local variable 'answer' could be declared final
- 🟡 `pmd:LiteralsFirstInComparisons` L1077
字符串比较时应将字面量放在前面
建议: 使用 "BAZ".equals(buz) 避免 NPE。
- 🟡 `pmd:UnnecessaryCaseChange` L1077
使用 toUpperCase/toLowerCase().equals() 不如 equalsIgnoreCase 清晰
建议: 改为 s1.equalsIgnoreCase(s2)。
- 🟡 `pmd:UseLocaleWithCaseConversions` L1077
When doing a String.toLowerCase()/toUpperCase() call, use a Locale
- 🟡 `pmd:AtLeastOneConstructor` L1083
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1084
Public member 'method1' declared in a non-public type
- 🟡 `pmd:PublicMemberInNonPublicType` L1087
Public member 'method' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L1087
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:UnusedNullCheckInEquals` L1088
equals() 中的 null 检查未被使用或位置不当
建议: 直接调用非空对象.equals(),或先用 Objects.equals() 统一判空。
- 🟡 `pmd:AtLeastOneConstructor` L1095
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1097
Missing commented default access modifier on method 'bar()'
- 🟡 `pmd:AvoidCatchingGenericException` L1100
Avoid catching Exception in try-catch block
- 🟡 `pmd:CommentDefaultAccessModifier` L1104
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:AtLeastOneConstructor` L1109
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1111
Missing commented default access modifier on method 'bar()'
- 🟡 `pmd:AtLeastOneConstructor` L1118
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1119
Missing commented default access modifier on method 'bar()'
- 🟡 `pmd:AvoidDuplicateLiterals` L1120
字符串字面量重复出现多次
建议: 提取为常量,避免重复字符串字面量。
- 🟡 `pmd:CommentDefaultAccessModifier` L1125
Missing commented default access modifier on method 'buz(String)'
- 🟡 `pmd:AtLeastOneConstructor` L1130
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1131
Missing commented default access modifier on method 'foo()'
- 🟡 `pmd:JumbledIncrementer` L1133
内层循环修改了外层循环的递增变量,循环逻辑混乱
建议: 确保内层循环更新自己的控制变量,不要更新外层循环变量。
- 🟡 `pmd:LocalVariableCouldBeFinal` L1133
Local variable 'k' could be declared final
- 🟡 `pmd:AvoidReassigningLoopVariables` L1133
Avoid reassigning the loop control variable 'i'
- 🟡 `pmd:AtLeastOneConstructor` L1141
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1142
Missing commented default access modifier on method 'foo()'
- 🟡 `pmd:AvoidLiteralsInIfCondition` L1144
Avoid using literals such as 5 in if statements
- 🟡 `pmd:AtLeastOneConstructor` L1152
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1153
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L1154
Local variable 'numbers' could be declared final
- 🟡 `pmd:CollectionTypeMismatch` L1155
集合操作使用了与泛型类型不匹配的对象
建议: 确保存入/取出/删除的元素类型与泛型一致,例如用 Integer 而不是 String。
- 🟡 `pmd:UseConcurrentHashMap` L1156
并发访问场景应使用 ConcurrentHashMap
建议: 将 HashMap 改为 ConcurrentHashMap,或同步访问。
- 🟡 `pmd:LocalVariableCouldBeFinal` L1156
Local variable 'map' could be declared final
- 🟡 `pmd:UselessPureMethodCall` L1157
Do not call pure method get if the result is not used.
- 🟡 `pmd:CollectionTypeMismatch` L1157
Object of type 'int' cannot be in collection expecting 'java.lang.String'
- 🟡 `pmd:LocalVariableCouldBeFinal` L1158
Local variable 'names' could be declared final
- 🟡 `pmd:UselessPureMethodCall` L1159
Do not call pure method contains if the result is not used.
- 🟡 `pmd:CollectionTypeMismatch` L1159
Object of type 'int' cannot be in collection expecting 'java.lang.String'
- 🟡 `pmd:AtLeastOneConstructor` L1164
Each class should declare at least one constructor
- 🟡 `pmd:AtLeastOneConstructor` L1165
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1165
Missing commented default access modifier on nested class 'C'
- 🟡 `pmd:CommentDefaultAccessModifier` L1166
Missing commented default access modifier on method 'varargs(Object[])'
- 🟡 `pmd:CommentDefaultAccessModifier` L1167
Missing commented default access modifier on method 'call()'
- 🟡 `pmd:ConfusingArgumentToVarargsMethod` L1168
可变参数调用意图不清晰
建议: 显式转换为 Object 或 Object[],或直接展开参数,避免歧义。
- 🟡 `pmd:ConfusingArgumentToVarargsMethod` L1169
Unclear if a varargs or non-varargs call is intended. Cast to Object or Object[] to clarify intent.
- 🟡 `pmd:AtLeastOneConstructor` L1175
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1176
Missing commented default access modifier on method 'bar(Object, String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L1176
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L1176
Parameter 'baz' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L1184
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateField` L1186
Avoid unused private fields such as 'stream'.
- 🟡 `pmd:NonSerializableClass` L1186
可序列化类包含不可序列化的字段
建议: 将该字段标记为 transient,或改为可序列化类型。
- 🟡 `pmd:AtLeastOneConstructor` L1190
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1191
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:CommentDefaultAccessModifier` L1198
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:AtLeastOneConstructor` L1204
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1205
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:AtLeastOneConstructor` L1215
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1216
Missing commented default access modifier on method 'foo()'
- 🟡 `pmd:AvoidLiteralsInIfCondition` L1219
Avoid using literals such as 25 in if statements
- 🟡 `pmd:AtLeastOneConstructor` L1228
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L1229
Missing commented default access modifier on method 'foo()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L1230
Local variable 'i' could be declared final
- 🟡 `pmd:LocalVariableCouldBeFinal` L1231
Local variable 'b' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L1237
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1238
Public member 'bar' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L1238
Parameter 'string' is not assigned and could be declared final
- 🟡 `pmd:LiteralsFirstInComparisons` L1239
Position literals first in String comparisons
- 🟡 `pmd:OnlyOneReturn` L1240
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:LiteralsFirstInComparisons` L1242
Position literals first in String comparisons
- 🟡 `pmd:OnlyOneReturn` L1243
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:AtLeastOneConstructor` L1252
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1254
Public member 'clone' declared in a non-public type
- 🟡 `pmd:CloneMethodReturnTypeMustMatchClassName` L1254
clone() 返回类型必须与类名一致
建议: 将 clone() 返回类型改为当前类名。
- 🟡 `pmd:CloneMethodMustImplementCloneable` L1254
只有实现 Cloneable 接口才应实现 clone() 方法
建议: 要么移除 clone() 方法,要么让类实现 Cloneable。
- 🟡 `pmd:AtLeastOneConstructor` L1260
Each class should declare at least one constructor
- 🟡 `pmd:CloneMethodReturnTypeMustMatchClassName` L1262
The return type of the clone() method must be the class name when implements Cloneable
- 🟡 `pmd:CloneMethodMustBePublic` L1262
实现 Cloneable 时 clone() 方法必须为 public
建议: 将 protected clone() 改为 public CloneableType clone()。
- 🟡 `pmd:OnlyOneReturn` L1264
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:AtLeastOneConstructor` L1272
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1274
Public member 'clone' declared in a non-public type
- 🟡 `pmd:CloneMethodReturnTypeMustMatchClassName` L1274
The return type of the clone() method must be the class name when implements Cloneable
- 🟡 `pmd:OnlyOneReturn` L1276
A method should have only one exit point, and that should be the last statement in the method
- 🟡 `pmd:AtLeastOneConstructor` L1284
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L1286
Public member 'clone' declared in a non-public type
- 🟡 `pmd:CloneMethodReturnTypeMustMatchClassName` L1286
The return type of the clone() method must be the class name when implements Cloneable
- 🟡 `pmd:AtLeastOneConstructor` L1294
Each class should declare at least one constructor
- 🟡 `pmd:EmptyFinalizer` L1296
finalize() 方法为空,没有实际作用
建议: 删除空 finalize 方法,或使用 Cleaner 清理资源。
- 🟡 `pmd:AtLeastOneConstructor` L1301
Each class should declare at least one constructor
- 🟡 `pmd:FinalizeDoesNotCallSuperFinalize` L1304
finalize() 方法应最后调用 super.finalize()
建议: 在 finalize() 末尾添加 super.finalize()。
- 🟡 `pmd:CommentDefaultAccessModifier` L1306
Missing commented default access modifier on method 'cleanup()'
- 🟡 `pmd:AtLeastOneConstructor` L1311
Each class should declare at least one constructor
- 🟡 `pmd:FinalizeOnlyCallsSuperFinalize` L1313
finalize() 只调用 super.finalize(),没有实际清理逻辑
建议: 删除无意义的 finalize,或在其中加入真正的资源清理逻辑。
- 🟡 `pmd:AtLeastOneConstructor` L1319
Each class should declare at least one constructor
- 🟡 `pmd:FinalizeOnlyCallsSuperFinalize` L1320
Finalize should do something besides just calling super.finalize()
- 🟡 `pmd:MissingOverride` L1320
The method 'finalize()' is missing an @Override annotation.
- 🟡 `pmd:FinalizeOverloaded` L1323
finalize 方法不应被重载
建议: 删除重载的 finalize(int) 方法。
- 🟡 `pmd:AtLeastOneConstructor` L1328
Each class should declare at least one constructor
- 🟡 `pmd:FinalizeOnlyCallsSuperFinalize` L1330
Finalize should do something besides just calling super.finalize()
- 🟡 `pmd:FinalizeShouldBeProtected` L1330
finalize() 应声明为 protected
建议: 将 public finalize() 改为 protected finalize()。
- 🟡 `pmd:PublicMemberInNonPublicType` L1330
Public member 'finalize' declared in a non-public type
- 🟡 `pmd:AtLeastOneConstructor` L1338
Each class should declare at least one constructor
- 🟡 `pmd:ProperLogger` L1339
logger 应定义为 private static final,并持有正确的类
建议: 改为 private static final Logger LOG = LoggerFactory.getLogger(Class.class);
- 🟡 `pmd:AtLeastOneConstructor` L1343
Each class should declare at least one constructor
- 🟡 `pmd:ProperLogger` L1344
Logger should be defined private static final and have the correct class
- 🟡 `pmd:CommentDefaultAccessModifier` L1345
Missing commented default access modifier on method 'bar()'
- 🟡 `pmd:AvoidCatchingGenericException` L1348
Avoid catching Exception in try-catch block
- 🟡 `pmd:CommentDefaultAccessModifier` L1352
Missing commented default access modifier on method 'doWork()'
- 🟡 `pmd:MissingSerialVersionUID` L1359
Classes implementing Serializable should set a serialVersionUID
- 🟡 `pmd:AtLeastOneConstructor` L1359
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateField` L1360
Avoid unused private fields such as 'value'.
- 🟡 `pmd:AtLeastOneConstructor` L1364
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateField` L1366
Avoid unused private fields such as 'nonSerializableField'.
- 🟡 `pmd:ImmutableField` L1366
Field 'nonSerializableField' may be declared final
- 🟡 `pmd:PublicMemberInNonPublicType` L1378
Public member 'getInstance' declared in a non-public type
- 🟡 `pmd:PublicMemberInNonPublicType` L1390
Public member 'getInstance' declared in a non-public type
- 🟡 `pmd:NonThreadSafeSingleton` L1391
单例实现不是线程安全的
建议: 使用 enum 单例、静态持有者(holder)或双重检查加 volatile。
- 🔵 `pmd:UnnecessaryFullyQualifiedName` L402
不必要使用全限定名
建议: 使用已导入的简单类名代替全限定名。
- 🔵 `pmd:DoNotThrowExceptionInFinally` L727
在 finally 块中抛出异常会使控制流难以理解
建议: 不要在 finally 中抛出异常,先记录或吞掉 finally 中的异常。
- 🔵 `pmd:InstantiationToGetClass` L801
不要仅为获取 Class 对象而实例化
建议: 使用 Integer.class 而不是 new Integer(1).getClass()。
- 🔵 `pmd:StringBufferInstantiationWithChar` L904
new StringBuffer(char) 会把 char 隐式转为 int 容量
建议: 使用 new StringBuffer() 或 new StringBuffer("c") 明确意图。
- 🔵 `pmd:InvalidLogMessageFormat` L1112
日志消息格式参数数量不匹配
建议: 修正占位符数量:一个 {} 对应一个参数。
- 🔵 `pmd:InvalidLogMessageFormat` L1113
Too many arguments, expected 1 argument but found 2
- 🔵 `pmd:UnnecessaryFullyQualifiedName` L1184
Unnecessary qualifier 'java.io': 'Serializable' is already in scope because it is imported in this file
AI 审查 · 9 条建议
- 🔴 [AI] [bug] `rethrow-missing-throws` L48
**捕获 IOException 后重新抛出但方法未声明 throws IOException,编译失败**
ReThrow.bad() 中 catch (IOException e) 后直接 throw e,但 bad() 没有 throws IOException,无法编译。
建议: 在方法签名上增加 throws IOException,或者更简单:不要捕获该异常,直接让 doWork() 的异常向外传播。
- 🔴 [AI] [bug] `wrap-same-missing-throws` L61
**包装 IOException 抛出但方法未声明 throws IOException,编译失败**
WrapSame.bad() 中 catch 后 throw new IOException(...),但 bad() 未声明 throws IOException,代码无法编译。
建议: 为 bad() 增加 throws IOException,或捕获后改为抛出一个非受检异常。
- 🔴 [AI] [bug] `finalize-protected-inaccessible` L565
**显式调用 Object.finalize() 违反访问控制,无法编译**
CallFinalize.bad() 中通过 Object 引用调用 o.finalize(),但 Object.finalize() 是 protected 方法,不在同包且不是通过子类引用访问,编译不通过。
建议: 删除该调用;如果需要清理资源,使用 AutoCloseable/Cleaner。
- 🔴 [AI] [bug] `null-inputstream-skip-npe` L637
**InputStream 初始化为 null 后直接调用 skip(),必现 NPE**
CheckSkip.bad() 中 InputStream in = null,随后调用 in.skip(10),运行时必然抛出 NullPointerException。
建议: 初始化真实流,并用 try-with-resources 管理生命周期,同时检查 skip 返回值。
- 🔴 [AI] [performance] `infinite-loop-inner-increment` L1133
**内层循环误递增外层变量 i,且 k 永不变,导致无限循环**
JumbledInc.foo() 的内层循环 for (int k = 0; k < 20; i++) 更新的是 i 而不是 k,k 恒为 0,内层循环永不退出,程序将挂起。
建议: 内层循环应递增自己的控制变量 k。
- 🟡 [AI] [design] `bean-getter-setter-naming` L317
**getter/setter 未遵循 JavaBean 命名规范,影响框架绑定**
BadBean 中 getname/setname 不符合 JavaBean 规范,应为 getName/setName,否则很多序列化/绑定框架无法识别。
建议: 将 getter 改为 getName()setter 改为 setName(String name)。
- 🟡 [AI] [security] `singleton-cast-classcastexception` L1039
**重载 getInstance(Object) 中无类型检查直接强转,会抛 ClassCastException**
SingletonDemo.getInstance(Object obj) 直接 (SingletonDemo) obj,传入非 SingletonDemo 对象时抛出 ClassCastException,且该重载破坏了单例语义。
建议: 删除该重载方法;如果确需接收对象,应先 instanceof 校验后再处理。
- 🟡 [AI] [bug] `log-exception-as-string` L1101
**日志只输出异常的 toString,丢失堆栈信息**
CorrectLog.bar() 中 _LOG.error(String.valueOf(e)) 只记录异常字符串,无法看到堆栈;应把异常对象作为最后一个参数传给日志 API。
建议: 使用 _LOG.error("doWork failed", e),保留异常堆栈。
- 🟡 [AI] [bug] `loop-break-on-first-iteration` L1222
**循环第一次迭代就 break,后续逻辑成为死代码**
BranchLastInLoop.foo() 中 if (i > 25) 永远不成立(i 最大为 9),而循环体末尾的 break 无条件执行,导致循环只执行一次。
建议: 检查循环终止条件,删除多余的 break,或把 break 放入有意义的条件判断中。
@@ -0,0 +1,52 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\codestyle\extra\EJBNamingDemo.java`
**语言:** java
**耗时:** 213.0s
**分析工具:** pmd
---
总计: 11 | 错误: 3 | 警告: 2 | 建议: 6
静态分析 · 8 个问题
- 🔴 `pmd:SystemPrintln` L35
第 35 行:使用了 System.out/err 输出。
建议: 避免直接使用 System.out.println,改用日志框架;例如使用 java.util.logging.Logger。
- 🟡 `pmd:AtLeastOneConstructor` L22
第 22 行:每个类应至少声明一个构造器。
建议: 为 MissingBeanSuffix 添加 public 无参构造器(如 public MissingBeanSuffix() {}),不要依赖编译器生成的默认构造器。
- 🔵 `pmd:UnnecessaryImport` L11
第 11 行:重复导入 'javax.ejb.EJBObject'。
建议: 删除第 11 行重复的 import javax.ejb.EJBObject,只保留第 8 行的一次导入。
- 🔵 `pmd:LocalHomeNamingConvention` L14
第 14 行:会话 EJB 的本地 Home 接口应以 LocalHome 作为后缀。
建议: 将接口名从 MissingLocalHomeSuffixBean 改为 MissingLocalHomeSuffixLocalHome,使其以 LocalHome 结尾。
- 🔵 `pmd:LocalInterfaceSessionNamingConvention` L18
第 18 行:会话 EJB 的本地接口应以 Local 作为后缀。
建议: 将接口名从 MissingLocalSuffixBean 改为 MissingLocalSuffixLocal,使其以 Local 结尾。
- 🔵 `pmd:MDBAndSessionBeanNamingConvention` L22
第 22 行:SessionBean/MessageBean 实现类应以 Bean 作为后缀。
建议: 将类名从 MissingBeanSuffix 改为 MissingSuffixBean,使其以 Bean 结尾。
- 🔵 `pmd:RemoteInterfaceNamingConvention` L26
第 26 行:会话 EJB 的远程接口不应带有后缀。
建议: 将接口名从 BadSuffixSession 改为 BadSuffix,去掉 Session 后缀。
- 🔵 `pmd:RemoteSessionInterfaceNamingConvention` L30
第 30 行:会话 EJB 的远程 Home 接口应以 Home 作为后缀。
建议: 将接口名从 MissingHomeSuffixEJB 改为 MissingHomeSuffixHome,使其以 Home 结尾。
AI 审查 · 3 条建议
- 🔴 [AI] [bug] `multiple-public-top-level-types` L14
**一个源文件中存在多个 public 顶层类型**
第 14、18、22、26、30 行都声明了 public 顶层接口/类。Java 规定每个编译单元只能有一个 public 顶层类型,且源文件名必须与该 public 类型名一致,否则编译失败。
建议: 将每个 public 类型拆分为独立的 .java 文件(文件名与类型名一致);若这些类型不需要外部访问,可将除一个之外的 public 改为包私有。
- 🔴 [AI] [bug] `session-bean-methods-not-implemented` L22
**SessionBean 实现类缺少必需的方法**
MissingBeanSuffix 是具体类,实现了 javax.ejb.SessionBean,但没有实现接口要求的方法(ejbActivate、ejbPassivate、ejbRemove、setSessionContext),导致编译失败。
建议: 补全这四个方法的空实现。由于 EJB Bean 类不能是 abstract,不能通过改为抽象类来绕过。
- 🟡 [AI] [design] `deprecated-ejb-2-api` L22
**使用了已废弃的 EJB 2.x SessionBean API**
MissingBeanSuffix 实现的是 javax.ejb.SessionBean,这是 EJB 2.x 时代的接口;同时 Home/Object 接口也是 EJB 2.x 模式,这类 API 在现代 EJB 容器中已过时。
建议: 如有条件,迁移到 EJB 3.x:在 Bean 类上使用 @Stateless/@Stateful 注解,并通过 @Local/@Remote 注解暴露业务接口,避免实现大量回调方法和手工维护 Home/Component 接口。
@@ -0,0 +1,68 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\performance\extra\FileItemDemo.java`
**语言:** java
**耗时:** 170.1s
**分析工具:** pmd
---
总计: 16 | 错误: 3 | 警告: 12 | 建议: 1
静态分析 · 12 个问题
- 🔴 `pmd:SystemPrintln` L14
L14:使用了 System.out/err 输出。
建议: 使用 java.util.logging 或 SLF4J/Log4j2 输出,便于统一日志级别和格式。
- 🔴 `pmd:SystemPrintln` L19
L19:使用了 System.out/err 输出。
建议: 用日志记录器替换 System.out.println。
- 🔴 `pmd:SystemPrintln` L25
L25:使用了 System.out/err 输出。
建议: 在入口类中使用日志记录器输出,或确认该输出仅用于命令行演示且不会被生产使用。
- 🟡 `pmd:AtLeastOneConstructor` L11
L11:每个类应至少声明一个构造器。
建议: 为 UseIOStreamFileItem 添加显式默认构造器;如果不希望外部实例化,可将构造器声明为 private。
- 🟡 `pmd:CommentDefaultAccessModifier` L12
L12:方法 process(FileItem) 缺少默认访问修饰符的注释。
建议: 为包级私有方法添加 /* default */ 注释,或显式改为 public/private/protected,以明确访问意图。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L12
L12:参数 item 未被重新赋值,可以声明为 final。
建议: 将方法签名中的 FileItem item 改为 final FileItem item,避免方法体内意外重新赋值。
- 🟡 `pmd:LocalVariableCouldBeFinal` L13
L13:局部变量 data 未被重新赋值,可以声明为 final。
建议: 将 byte[] data 改为 final byte[] data,表达只读引用的意图。
- 🟡 `pmd:UseIOStreamsWithApacheCommonsFileItem` L13
L13:应避免调用高内存占用的 FileItem.get() 或 FileItem.getString()。
建议: 如果只需要文件大小,使用 item.getSize();如果需要内容,使用 item.getInputStream() 配合 try-with-resources 流式读取,避免将整个文件载入内存。
- 🟡 `pmd:CommentDefaultAccessModifier` L17
L17:方法 processString(FileItem) 缺少默认访问修饰符的注释。
建议: 与 process 一致,添加 /* default */ 注释或使用显式访问修饰符。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L17
L17:参数 item 未被重新赋值,可以声明为 final。
建议: 将方法签名中的 FileItem item 改为 final FileItem item。
- 🟡 `pmd:LocalVariableCouldBeFinal` L18
L18:局部变量 s 未被重新赋值,可以声明为 final。
建议: 将 String s 改为 final String s。
- 🟡 `pmd:UseIOStreamsWithApacheCommonsFileItem` L18
L18:应避免调用高内存占用的 FileItem.get() 或 FileItem.getString()。
建议: 改为读取输入流并显式指定 UTF-8 字符集,使用 try-with-resources 关闭输入流;避免 FileItem.getString() 使用默认字符集。
AI 审查 · 4 条建议
- 🟡 [AI] [performance] `use-getsize-for-length-only` L13
**process() 只需要文件长度时却把整个文件读入内存**
process(FileItem) 中仅用 data.length 获取字节数,但 FileItem.get() 会一次把整个上传文件载入 byte[]。当文件很大时会造成不必要的内存占用,甚至导致 OOM。FileItem.getSize() 可以在不读取内容的情况下返回文件大小。
建议: 将 byte[] data = item.get() 改为 long size = item.getSize(),并把 data.length 改为 size。若后续需要内容,再使用 item.getInputStream() 配合 try-with-resources 流式读取。
- 🟡 [AI] [security] `enforce-upload-size-limits` L13
**未限制上传文件大小,存在内存耗尽风险**
代码直接对 FileItem 调用 get()/getString() 将完整内容读入内存。若 FileItem 来自不受信任的 HTTP multipart 上传,攻击者可提交超大文件,导致 JVM 堆内存被耗尽。虽然静态分析建议改用 getInputStream(),但流式读取仍应配合上传大小上限。
建议: 在解析上传时配置 ServletFileUpload.setFileSizeMax()/setSizeMax(),或将 DiskFileItemFactory 的阈值调低使大文件写入临时文件;读取前检查 item.getSize()。
- 🟡 [AI] [bug] `explicit-charset-for-fileitem-read` L18
**FileItem.getString() 使用平台默认字符集,导致编码不一致**
FileItem.getString() 未指定字符集时会使用运行平台的默认字符集。开发环境与生产环境字符集不同(如本地 GBK、服务器 UTF-8)时,读取同一表单字段或文件内容会得到不同结果。应显式指定 UTF-8 或与业务约定的编码。
建议: 调用 item.getString(StandardCharsets.UTF_8.name());若按静态分析改为 getInputStream() 流式读取,也要使用显式字符集的 Reader,并在 try-with-resources 中关闭流。
- 🔵 [AI] [design] `explicit-access-modifiers` L12
**类及方法使用隐式包级私有访问权限**
UseIOStreamFileItem 的 process/processString 没有显式访问修饰符,默认为包级私有。当前代码中这两个方法未被类内部调用,也未声明为 private;如果实际需要外部访问,包级私有会限制可见性;如果仅是辅助方法,应缩小为 private。
建议: 若方法仅类内部使用,添加 private 修饰符;若需对外提供,请将 UseIOStreamFileItem 放入以类名命名的独立文件并声明 public,同时为方法添加 public。
@@ -0,0 +1,273 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\design\extra\GodClassDemo.java`
**语言:** java
**耗时:** 197.9s
**分析工具:** pmd
---
总计: 84 | 错误: 3 | 警告: 78 | 建议: 3
静态分析 · 79 个问题
- 🔴 `pmd:AvoidReassigningParameters` L57
L57: 避免对参数 'x' 重新赋值
建议: 在方法内使用局部变量保存 x 的初始值,并对局部变量进行递减操作,保持参数不变。
- 🔴 `pmd:AvoidReassigningParameters` L78
L78: 避免对参数 'x' 重新赋值
建议: 在方法内使用局部变量保存 x 的初始值,并对局部变量进行递减操作,保持参数不变。
- 🔴 `pmd:SystemPrintln` L181
L181: 使用了 System.out/err 输出
建议: 使用日志框架(如 java.util.logging、SLF4J、Log4j2)记录信息,便于日志管理与级别控制。
- 🟡 `pmd:AtLeastOneConstructor` L9
L9: 每个类应至少声明一个构造函数
建议: 为类添加构造函数;若无需初始化逻辑,可声明一个空的包可见构造函数。
- 🟡 `pmd:DataClass` L9
L9: 类 'ExternalData' 被怀疑是数据类(WOC=0.000%, NOPA=10, NOAM=0, WMC=0
建议: 将公共字段改为私有,并添加构造器与行为方法;或使用 Java record 作为不可变数据传输对象(Java 14+)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'a' 应降低可见性
建议: 将字段 a 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'b' 应降低可见性
建议: 将字段 b 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'c' 应降低可见性
建议: 将字段 c 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'd' 应降低可见性
建议: 将字段 d 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'e' 应降低可见性
建议: 将字段 e 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'f' 应降低可见性
建议: 将字段 f 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'g' 应降低可见性
建议: 将字段 g 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'h' 应降低可见性
建议: 将字段 h 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'i' 应降低可见性
建议: 将字段 i 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:PublicMemberInNonPublicType` L10
L10: 非公共类型 'ExternalData' 中的公共成员 'j' 应降低可见性
建议: 将字段 j 改为 private,并对外提供必要的 getter/setter(如果确实需要访问)。
- 🟡 `pmd:AtLeastOneConstructor` L14
L14: 每个类应至少声明一个构造函数
建议: 为 GodClassDemo 添加构造函数;若该类仅作为工具类,建议将构造函数设为 private 禁止实例化。
- 🟡 `pmd:GodClass` L14
L14: 疑似上帝类(WMC=89, ATFD=105, TCC=0.000%
建议: 按单一职责将 GodClassDemo 拆分为多个类,将规则方法分组到不同类,并提升方法内聚性、降低对外部数据类的直接访问。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L16
L16: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L16
L16: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L18
L18: 避免在 if 语句中使用字面量(如 1)
建议: 定义常量并替换:private static final int THRESHOLD_1 = 1; 条件改为 x > THRESHOLD_1。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L19
L19: 避免在 if 语句中使用字面量(如 2)
建议: 定义常量并替换:private static final int THRESHOLD_2 = 2; 条件改为 x > THRESHOLD_2。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L22
L22: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L22
L22: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L24
L24: 避免在 if 语句中使用字面量(如 1)
建议: 定义常量并替换:private static final int THRESHOLD_1 = 1; 条件改为 x > THRESHOLD_1。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L25
L25: 避免在 if 语句中使用字面量(如 2)
建议: 定义常量并替换:private static final int THRESHOLD_2 = 2; 条件改为 x > THRESHOLD_2。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L28
L28: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L28
L28: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L34
L34: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L34
L34: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L46
L46: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L46
L46: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L52
L52: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L56
L56: 避免在 if 语句中使用字面量(如 10)
建议: 定义常量并替换:private static final int THRESHOLD_10 = 10; 条件改为 x > THRESHOLD_10。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L61
L61: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L61
L61: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L69
L69: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L82
L82: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L82
L82: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L84
L84: 避免在 if 语句中使用字面量(如 1)
建议: 定义常量并替换:private static final int THRESHOLD_1 = 1; 条件改为 x > THRESHOLD_1。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L84
L84: 避免在 if 语句中使用字面量(如 2)
建议: 定义常量并替换:private static final int THRESHOLD_2 = 2; 条件改为 x > THRESHOLD_2。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L85
L85: 避免在 if 语句中使用字面量(如 3)
建议: 定义常量并替换:private static final int THRESHOLD_3 = 3; 条件改为 x > THRESHOLD_3。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L88
L88: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L88
L88: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L97
L97: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L97
L97: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L99
L99: 避免在 if 语句中使用字面量(如 5)
建议: 定义常量并替换:private static final int THRESHOLD_5 = 5; 条件改为 x > THRESHOLD_5。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L100
L100: 避免在 if 语句中使用字面量(如 10)
建议: 定义常量并替换:private static final int THRESHOLD_10 = 10; 条件改为 x > THRESHOLD_10。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L103
L103: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L103
L103: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:TooFewBranchesForSwitch` L106
L106: 分支少于三个的 switch 效率较低,建议改用 if 语句
建议: 将 switch (i % 2) 改为 if-elseif (i % 2 == 0) { r += d.a; } else { r += d.b; }
- 🟡 `pmd:AvoidLiteralsInIfCondition` L111
L111: 避免在 if 语句中使用字面量(如 5)
建议: 定义常量并替换:private static final int THRESHOLD_5 = 5; 条件改为 x > THRESHOLD_5。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L114
L114: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L114
L114: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L116
L116: 避免在 if 语句中使用字面量(如 1)
建议: 定义常量并替换:private static final int THRESHOLD_1 = 1; 条件改为 x > THRESHOLD_1。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L117
L117: 避免在 if 语句中使用字面量(如 2)
建议: 定义常量并替换:private static final int THRESHOLD_2 = 2; 条件改为 x > THRESHOLD_2。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L120
L120: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L120
L120: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L122
L122: 避免在 if 语句中使用字面量(如 1)
建议: 定义常量并替换:private static final int THRESHOLD_1 = 1; 条件改为 x > THRESHOLD_1。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L123
L123: 避免在 if 语句中使用字面量(如 2)
建议: 定义常量并替换:private static final int THRESHOLD_2 = 2; 条件改为 x > THRESHOLD_2。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L126
L126: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L126
L126: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L128
L128: 避免在 if 语句中使用字面量(如 1)
建议: 定义常量并替换:private static final int THRESHOLD_1 = 1; 条件改为 x > THRESHOLD_1。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L129
L129: 避免在 if 语句中使用字面量(如 2)
建议: 定义常量并替换:private static final int THRESHOLD_2 = 2; 条件改为 x > THRESHOLD_2。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L132
L132: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L132
L132: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L135
L135: 避免在 if 语句中使用字面量(如 10)
建议: 定义常量并替换:private static final int THRESHOLD_10 = 10; 条件改为 i > THRESHOLD_10。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L135
L135: 避免在 if 语句中使用字面量(如 20)
建议: 定义常量并替换:private static final int THRESHOLD_20 = 20; 条件改为 i > THRESHOLD_20。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L140
L140: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L140
L140: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L142
L142: 避免在 if 语句中使用字面量(如 1)
建议: 定义常量并替换:private static final int THRESHOLD_1 = 1; 条件改为 x > THRESHOLD_1。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L142
L142: 避免在 if 语句中使用字面量(如 2)
建议: 定义常量并替换:private static final int THRESHOLD_2 = 2; 条件改为 x > THRESHOLD_2。
- 🟡 `pmd:AvoidLiteralsInIfCondition` L143
L143: 避免在 if 语句中使用字面量(如 3)
建议: 定义常量并替换:private static final int THRESHOLD_3 = 3; 条件改为 x > THRESHOLD_3。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L146
L146: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L146
L146: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L152
L152: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L152
L152: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L168
L168: 参数 'd' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal ExternalData d。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L168
L168: 参数 'x' 未被赋值,可声明为 final
建议: 将参数声明为 finalfinal int x。
- 🔵 `pmd:OneDeclarationPerLine` L10
L10: 每行只声明一个变量,以增强代码可读性
建议: 将同一行的多个变量声明拆分为多行,每行一个变量。
AI 审查 · 5 条建议
- 🟡 [AI] [bug] `potential-null-dereference` L16
**ExternalData 参数未做空值校验**
所有 rule* 方法直接使用参数 d 的字段,未校验 d 是否为 null。当外部传入 null 时,方法会立即抛出 NullPointerException。
建议: 在每个方法入口增加防御性判断,如 if (d == null) throw new IllegalArgumentException("d must not be null");或使用 Objects.requireNonNull(d) 统一校验。
- 🟡 [AI] [bug] `unreachable-branch-in-if-else-if` L18
**if-else if 条件顺序导致后续分支不可达**
rule1、rule2、rule9、rule11、rule13、rule14、rule15、rule16、rule17 等方法中的 if-else if 链按从小到大判断,例如 rule1 中 if (x>0) 已覆盖所有正数,其后的 else if (x>1) 与 else if (x>2) 永远无法执行。
建议: 调整判断顺序,将范围更大的条件放在前面,或改用区间判断(如 x > 0 && x <= 1)。请根据业务语义改为正确的分段逻辑。
- 🟡 [AI] [bug] `tautological-condition` L31
**条件表达式恒为真**
rule3L31)与 rule18L149)中的 if (x > 1 || x < 20) 对任意整数 x 均成立,导致其分支总被执行,原条件失去判断意义。
建议: 检查业务意图。如果希望同时满足两个条件,应改为 if (x > 1 && x < 20);如果确实无条件执行,应移除 if 直接执行。
- 🔵 [AI] [design] `meaningless-method-names` L16
**规则方法使用无意义的数字命名**
rule1 到 rule20 的方法名无法描述业务行为,难以维护和理解。数字命名还暗示这些方法可能由复制粘贴生成,代码重复度高。
建议: 根据业务语义重命名方法(如 calculateDiscount、applyTax 等),并提取重复逻辑为公共方法。
- 🔵 [AI] [performance] `inefficient-nested-loop` L90
**rule10 存在 O(n²) 复杂度且可能产生巨大循环**
rule10 使用双重 for 循环(L90-94),当 x 较大时会造成严重的性能问题;若 x 来自用户输入,可能形成拒绝服务攻击。
建议: 评估业务逻辑,避免将未受控的外部输入直接作为循环上限;考虑降低时间复杂度或增加上限校验。
@@ -0,0 +1,49 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\org\example\beans\InvalidBeanDemo.java`
**语言:** java
**耗时:** 106.9s
**分析工具:** pmd
---
总计: 10 | 错误: 1 | 警告: 8 | 建议: 1
静态分析 · 7 个问题
- 🔴 `pmd:SystemPrintln` L30
使用了 System.out / System.err 输出。
建议: 请改用日志框架(如 java.util.logging.Logger、SLF4J)记录输出,以便控制日志级别、格式和输出目标。
- 🟡 `pmd:AtLeastOneConstructor` L7
每个类都应该声明至少一个构造函数。
建议: 请为 MyBean 添加显式的无参构造器,例如 `public MyBean() {}`,以保证符合类的基本构造约定。
- 🟡 `pmd:InvalidJavaBean` L8
Bean 'MyBean' 的属性 'Label' 缺少 setter。
建议: 请为 label 属性添加标准 setter 方法:`public void setLabel(String label) { this.label = label; }`
- 🟡 `pmd:AtLeastOneConstructor` L16
每个类都应该声明至少一个构造函数。
建议: 请为 WrapException 添加包私有无参构造器,例如 `WrapException() {}`
- 🟡 `pmd:CommentDefaultAccessModifier` L17
方法 'bar()' 缺少注释掉的默认访问修饰符。
建议: 请在无修饰符方法前添加 `/* default */` 注释,以明确其包私有可见性,如:`/* default */ void bar() { ... }`
- 🟡 `pmd:AvoidThrowingNewInstanceOfSameException` L21
应避免在 catch 块中仅捕获异常,然后包装成同一类型的新异常并抛出。
建议: 请直接抛出原始异常,例如 `throw se;`,或者包装为具有更明确语义的其他异常类型。
- 🟡 `pmd:CommentDefaultAccessModifier` L24
方法 'doWork()' 缺少注释掉的默认访问修饰符。
建议: 请在无修饰符方法前添加 `/* default */` 注释,如:`/* default */ void doWork() { ... }`
AI 审查 · 3 条建议
- 🟡 [AI] [design] `bean-not-serializable` L7
**JavaBean 未实现 Serializable**
MyBean 作为 JavaBean 未实现 java.io.Serializable,也未声明 serialVersionUID,在需要持久化或会话复制的场景中无法正常序列化。
建议: 为 MyBean 添加 `implements java.io.Serializable` 并声明 `private static final long serialVersionUID = 1L;`。同时建议补充无参构造器(静态分析已要求)和 setter。
- 🟡 [AI] [bug] `unreachable-catch-block` L20
**空方法调用后的 catch 块不可达**
doWork() 方法体为空,不会抛出任何异常,因此 bar() 中的 catch (IllegalStateException) 永远不会进入,属于死代码。异常处理流程在当前代码中无效。
建议: 若 doWork() 尚未实现,应删除 try-catch 并直接调用;若 doWork() 可能抛异常,应先补全方法体。建议去掉无意义的相同异常包装。
- 🔵 [AI] [style] `one-top-level-class-per-file` L16
**多个顶层类定义在同一个源文件中**
MyBean、WrapException、BeansMain 三个顶层类写在同一个 .java 文件中,使文件职责不单一,降低可读性和可维护性。
建议: 将 WrapException 和 BeansMain 分别抽取到独立源文件(WrapException.java、BeansMain.java),并为每个类保留必要的 public/包私有声明。
@@ -0,0 +1,81 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\JUnit3RulesTest.java`
**语言:** java
**耗时:** 213.2s
**分析工具:** pmd
---
总计: 20 | 错误: 4 | 警告: 14 | 建议: 2
静态分析 · 15 个问题
- 🔴 `pmd:MethodNamingConventions` L12
实例方法名 'TearDown' 不符合 '[a-z][a-zA-Z0-9]*' 命名规范(L12)。
建议: 将 TearDown() 重命名为 tearDown(),使其以大写字母开头变为小写开头,并作为 JUnit3 的清理方法使用。
- 🔴 `pmd:SystemPrintln` L30
使用了 System.out/errL30)。
建议: 在正式代码中改用日志框架,例如 java.util.logging.Logger;也可为 Junit3Main 注入输出流以便测试。
- 🟡 `pmd:AtLeastOneConstructor` L9
每个类都应至少声明一个构造函数(L9)。
建议: 为 JUnitSpellingTest 添加显式构造函数,例如:public JUnitSpellingTest() { super(); }。若该类保留为 public 且供 JUnit3 使用,这个公共无参构造函数也满足 JUnit3 反射实例化的要求。
- 🟡 `pmd:TestClassWithoutTestCases` L9
类 'JUnitSpellingTest' 可能是测试类,但未包含任何测试用例(L9)。
建议: 在该类中新增一个以 test 开头、返回 void、公共无参的测试方法,并添加断言。例如:public void testExample() { assertTrue(true); }。如果该类用于存放公共测试工具,则不应继承 TestCase。
- 🟡 `pmd:JUnitSpelling` L10
你可能拼错了 JUnit 框架方法(setUp 或 tearDown)(L10)。
建议: 将 setup() 重命名为 setUp(),确保 JUnit3 将其识别为初始化方法。若方法体为空,请补充资源初始化逻辑;否则该声明无实际作用。
- 🟡 `pmd:JUnitSpelling` L12
你可能拼错了 JUnit 框架方法(setUp 或 tearDown)(L12)。
建议: 将 TearDown() 重命名为 tearDown(),使其被 JUnit3 识别为 teardown 生命周期方法。
- 🟡 `pmd:AtLeastOneConstructor` L17
每个类都应至少声明一个构造函数(L17)。
建议: 为 JUnitStaticSuiteTest 添加显式构造函数,例如:public JUnitStaticSuiteTest() { super(); }。注意测试类本身还应为 public,才能被 JUnit3 外部加载。
- 🟡 `pmd:TestClassWithoutTestCases` L17
类 'JUnitStaticSuiteTest' 可能是测试类,但未包含任何测试用例(L17)。
建议: 将 suite() 改为 public static junit.framework.Test suite(),并返回包含测试方法的 TestSuite,例如:return new TestSuite(JUnitStaticSuiteTest.class)。同时确保类中至少有一个 test 开头的方法。
- 🟡 `pmd:PublicMemberInNonPublicType` L18
在非 public 类型 JUnitStaticSuiteTest 中声明了 public 成员 'suite'L18)。
建议: JUnit3 要求 suite() 为 public,因此最佳修复是将类 JUnitStaticSuiteTest 移到独立文件并声明为 public class JUnitStaticSuiteTest;不要简单地把方法改为包私有,否则 JUnit 无法调用 suite 入口。
- 🟡 `pmd:JUnitStaticSuite` L18
你有一个 suite() 方法不是 public 且 staticJUnit 不会调用它来获取 TestSuite。这是你期望的吗?(L18)
建议: 将方法签名改为 public static junit.framework.Test suite(),并返回一个 TestSuite 实例,例如 return new TestSuite(JUnitStaticSuiteTest.class)。
- 🟡 `pmd:AtLeastOneConstructor` L23
每个类都应至少声明一个构造函数(L23)。
建议: 为 DetachedTest 添加显式构造函数,例如:public DetachedTest() { super(); }。同时建议将类改为 public 并放入独立文件。
- 🟡 `pmd:DetachedTestCase` L24
可能存在脱离测试套件的 JUnit 测试用例(L24)。
建议: 确保测试类为 public,以便 JUnit3 反射实例化;并将该类纳入某个 TestSuite。若迁移到 JUnit4/5,请使用 @Test 注解替代 test 前缀。
- 🟡 `pmd:PublicMemberInNonPublicType` L24
在非 public 类型 DetachedTest 中声明了 public 成员 'testSomething'L24)。
建议: 将 DetachedTest 改为 public class,并放入独立文件 DetachedTest.java。JUnit3 测试方法必须为 public,因此不要降低方法的可见性。
- 🟡 `pmd:UnitTestShouldIncludeAssert` L24
此单元测试应包含 assert() 或 fail()L24)。
建议: 在 testSomething() 中添加有意义的断言,例如 assertEquals(2, 1 + 1)。空测试永远通过,无法保护代码。
- 🟡 `pmd:UnitTestShouldUseTestAnnotation` L24
单元测试应使用 @Test 注解,否则不会运行。对于 JUnit Jupiter,还可使用 @RepeatedTest@TestFactory@TestTemplate@ParameterizedTest 注解(L24)。
建议: 若迁移到 JUnit4/5,移除 TestCase 继承,在方法上添加 @Test,并使用 org.junit.jupiter.api.Assertions 断言。当前 JUnit3 风格可通过修正类可见性继续运行,但推荐升级。
AI 审查 · 5 条建议
- 🔴 [AI] [bug] `non-public-junit3-test-class` L17
**JUnit3 测试类必须声明为 public 才能被发现**
JUnitStaticSuiteTest 和 DetachedTest 都是包私有类。JUnit3 运行器通过反射从外部包加载测试类,非 public 类会导致测试被跳过或抛出 IllegalAccessException。即使方法都声明为 public,类本身不可见也无法运行。
建议: 将两个测试类分别放入独立文件,并声明为 public class。移动后,默认的 public 无参构造即可满足 JUnit3 的基本实例化要求。
- 🔴 [AI] [bug] `multiple-top-level-classes` L28
**多个顶层类与 Java 文件结构冲突,main 入口不可用**
本文件中的 JUnitSpellingTest 是 public 类,因此文件必须命名为 JUnitSpellingTest.java。Junit3Main 无法在同一文件中声明为 public,导致其 main 方法不能作为程序入口;同时 JUnitStaticSuiteTest 和 DetachedTest 不是 publicJUnit3 无法从外部包加载它们。这种多顶层类布局会造成测试被静默忽略、程序无法启动。
建议: 将 Junit3Main 移到独立文件并声明为 public class Junit3Main;将 JUnitStaticSuiteTest、DetachedTest 也分别移到独立文件并声明为 public class。如果使用 JUnit5,则无需继承 TestCase,文件结构更简单。
- 🟡 [AI] [design] `empty-test-suite` L24
**测试类没有真实断言,测试套件可能空转**
JUnitSpellingTest 没有任何 test 方法;JUnitStaticSuiteTest 只有无效的 suite() 且没有测试方法;DetachedTest.testSomething() 没有断言。这些测试即使全部通过也不能验证任何行为,容易让 CI 产生假阳性。
建议: 为每个测试类添加带断言的 test 方法;若某个类只是测试基类,则不应继承 TestCase。使用 JUnit5 的 @Test 和 Assertions 能更容易写出有效测试。
- 🔵 [AI] [design] `legacy-junit3` L6
**使用已停止维护的 JUnit3 测试框架**
代码通过继承 junit.framework.TestCase 和 test 前缀编写测试,属于 JUnit3 风格。JUnit3 不支持现代测试特性(如异常断言、参数化测试、嵌套测试),不利于长期维护。
建议: 迁移到 JUnit4 或 JUnit5:移除 extends TestCase,测试方法加 @Test 注解,使用 org.junit.jupiter.api.Assertions 断言。迁移前至少先修复类可见性和空测试问题。
- 🔵 [AI] [style] `abbreviation-in-name` L28
**类名 Junit3Main 中 JUnit 缩写大小写不规范**
JUnit 是一个品牌名,通常缩写应保持全部大写。Junit3Main 看起来像类名大小写不规范,建议改为 JUnit3Main,并同步更新文件名和所有引用。
建议: 将 Junit3Main 重命名为 JUnit3Main,更新文件名为 JUnit3Main.java,并修改 main 方法中 Logger.getLogger(Junit3Main.class.getName()) 的类名引用。
@@ -0,0 +1,245 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\JUnit4RulesTest.java`
**语言:** java
**耗时:** 228.6s
**分析工具:** pmd
---
总计: 74 | 错误: 12 | 警告: 62 | 建议: 0
静态分析 · 67 个问题
- 🔴 `pmd:WrongTestAnnotation` L11
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🔴 `pmd:WrongTestAnnotation` L19
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🔴 `pmd:WrongTestAnnotation` L25
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🔴 `pmd:WrongTestAnnotation` L39
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🔴 `pmd:WrongTestAnnotation` L47
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🔴 `pmd:WrongTestAnnotation` L53
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🔴 `pmd:AvoidThrowingNullPointerException` L63
避免抛出空指针异常。
建议: 不要显式 throw new NullPointerException();可改用 java.util.Objects.requireNonNull(null) 产生 NPE,或改抛更具体的异常并同步调整测试期望。
- 🔴 `pmd:WrongTestAnnotation` L69
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🔴 `pmd:WrongTestAnnotation` L79
org.junit.Test 是 JUnit 4 的注解,而当前代码库正在使用 JUnit Jupiter。
建议: 将导入改为 org.junit.jupiter.api.TestJUnit 5),并同步将 org.junit.Assert 迁移为 org.junit.jupiter.api.Assertions。
- 🟡 `pmd:AtLeastOneConstructor` L9
每个类都应声明至少一个构造函数。
建议: 为 JUnit4RulesTest 添加一个显式构造函数,避免依赖隐式公有无参构造器。
- 🟡 `pmd:LocalVariableCouldBeFinal` L13
局部变量 'a' 可以声明为 final。
建议: 将该局部变量标记为 final,防止意外重新赋值并提升可读性。
- 🟡 `pmd:LocalVariableCouldBeFinal` L14
局部变量 'b' 可以声明为 final。
建议: 将该局部变量标记为 final,防止意外重新赋值并提升可读性。
- 🟡 `pmd:SimplifiableTestAssertion` L15
该断言可以使用 assertEquals 简化。
建议: 用 assertEquals(a, b) 代替 assertTrue(a.equals(b)),并补充失败消息;若迁移到 JUnit Jupiter,应为 Assertions.assertEquals(a, b)。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L15
单元测试断言应包含失败消息。
建议: 为断言增加第一个 String 参数作为失败消息,例如 assertEquals("a should equal b", a, b)。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L21
单元测试断言应包含失败消息。
建议: 为 assertEquals 补充失败消息,例如 assertEquals("expected value", expected, actual)。
- 🟡 `pmd:UnitTestContainsTooManyAsserts` L26
单元测试不应包含超过 1 个断言。
建议: 将 testTooMany 拆分为多个测试方法,每个方法只保留一个断言;或使用 AssertJ 的软断言(assertSoftly)承载多个校验。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L27
单元测试断言应包含失败消息。
建议: 该断言本身无意义,建议删除;如果保留,必须提供消息,例如 assertTrue("message", condition)。
- 🟡 `pmd:UnnecessaryBooleanAssertion` L27
assertTrue(true) 或类似语句是不必要的。
建议: 删除对布尔常量 true 的断言;若需要固定验证,应改为对实际被测状态的断言。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L28
单元测试断言应包含失败消息。
建议: 该断言本身无意义,建议删除;如果保留,必须提供消息,例如 assertTrue("message", condition)。
- 🟡 `pmd:UnnecessaryBooleanAssertion` L28
assertTrue(true) 或类似语句是不必要的。
建议: 删除对布尔常量 true 的断言;若需要固定验证,应改为对实际被测状态的断言。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L29
单元测试断言应包含失败消息。
建议: 该断言本身无意义,建议删除;如果保留,必须提供消息,例如 assertTrue("message", condition)。
- 🟡 `pmd:UnnecessaryBooleanAssertion` L29
assertTrue(true) 或类似语句是不必要的。
建议: 删除对布尔常量 true 的断言;若需要固定验证,应改为对实际被测状态的断言。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L30
单元测试断言应包含失败消息。
建议: 该断言本身无意义,建议删除;如果保留,必须提供消息,例如 assertTrue("message", condition)。
- 🟡 `pmd:UnnecessaryBooleanAssertion` L30
assertTrue(true) 或类似语句是不必要的。
建议: 删除对布尔常量 true 的断言;若需要固定验证,应改为对实际被测状态的断言。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L31
单元测试断言应包含失败消息。
建议: 为 assertEquals 增加失败消息,例如 assertEquals("1 should equal 1", 1, 1)。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L32
单元测试断言应包含失败消息。
建议: 为 assertEquals 增加失败消息,例如 assertEquals("2 should equal 2", 2, 2)。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L33
单元测试断言应包含失败消息。
建议: 为 assertEquals 增加失败消息,例如 assertEquals("3 should equal 3", 3, 3)。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L34
单元测试断言应包含失败消息。
建议: 为 assertEquals 增加失败消息,例如 assertEquals("4 should equal 4", 4, 4)。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L35
单元测试断言应包含失败消息。
建议: 为 assertEquals 增加失败消息,例如 assertEquals("5 should equal 5", 5, 5)。
- 🟡 `pmd:LocalVariableCouldBeFinal` L41
局部变量 'actual' 可以声明为 final。
建议: 将该局部变量标记为 final,防止意外重新赋值并提升可读性。
- 🟡 `pmd:LocalVariableCouldBeFinal` L42
局部变量 'expected' 可以声明为 final。
建议: 将该局部变量标记为 final,防止意外重新赋值并提升可读性。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L43
单元测试断言应包含失败消息。
建议: 为 assertEquals 增加失败消息,并同时修正参数顺序:assertEquals("expected should equal actual", expected, actual)。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L49
单元测试断言应包含失败消息。
建议: 该断言本身无意义,建议删除;如果保留,必须提供消息,例如 assertTrue("message", condition)。
- 🟡 `pmd:UnnecessaryBooleanAssertion` L49
assertTrue(true) 或类似语句是不必要的。
建议: 删除对布尔常量 true 的断言;若需要固定验证,应改为对实际被测状态的断言。
- 🟡 `pmd:JUnitUseExpected` L55
在 JUnit4 中,应使用 @Test(expected) 标注预期会抛出异常的测试。
建议: 若使用 JUnit 4,改为 @Test(expected = NullPointerException.class) 并删除 try/catch;若已迁移到 JUnit Jupiter,使用 assertThrows(NullPointerException.class, () -> doSomething())。
- 🟡 `pmd:EmptyCatchBlock` L58
避免空 catch 块。
建议: 不要在 catch 块中留空;应使用 assertThrows 或 @Test(expected) 声明预期异常,或至少记录异常并重新抛出。
- 🟡 `pmd:AvoidCatchingGenericException` L58
避免在 try-catch 块中捕获 NullPointerException。
建议: 不要捕获并吞掉 NPE;在 JUnit Jupiter 下应使用 assertThrows 声明预期异常,而非手写 try/catch。
- 🟡 `pmd:AtLeastOneConstructor` L68
每个类都应声明至少一个构造函数。
建议: 为 MissingAfterTest 添加一个显式构造函数。
- 🟡 `pmd:PublicMemberInNonPublicType` L70
公共成员 'testCleanup' 声明在非公共类型中。
建议: 如果使用 JUnit Jupiter,可去掉 public 修饰;如果保留 JUnit 4,应将测试类声明为 public。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L71
单元测试断言应包含失败消息。
建议: 该断言本身无意义,建议删除;如果保留,必须提供消息,例如 assertTrue("message", condition)。
- 🟡 `pmd:UnnecessaryBooleanAssertion` L71
assertTrue(true) 或类似语句是不必要的。
建议: 删除对布尔常量 true 的断言;若需要固定验证,应改为对实际被测状态的断言。
- 🟡 `pmd:UnitTestShouldUseAfterAnnotation` L73
如果此方法用于测试清理,请使用正确的注解。
建议: 在 JUnit Jupiter 中使用 @AfterEach,在 JUnit 4 中使用 @After,并补充清理逻辑或删除空方法。
- 🟡 `pmd:DetachedTestCase` L73
可能是脱离的 JUnit 测试用例。
建议: 该方法名容易让 JUnit 误认为它是测试用例,但未使用生命周期注解;如果用于清理,请添加 @AfterEach/@After;否则删除或重命名。
- 🟡 `pmd:PublicMemberInNonPublicType` L73
公共成员 'tearDown' 声明在非公共类型中。
建议: 如果使用 JUnit Jupiter,可去掉 public 修饰;如果保留 JUnit 4,应将测试类声明为 public。
- 🟡 `pmd:AtLeastOneConstructor` L78
每个类都应声明至少一个构造函数。
建议: 为 MissingBeforeTest 添加一个显式构造函数。
- 🟡 `pmd:PublicMemberInNonPublicType` L80
公共成员 'testSetup' 声明在非公共类型中。
建议: 如果使用 JUnit Jupiter,可去掉 public 修饰;如果保留 JUnit 4,应将测试类声明为 public。
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L81
单元测试断言应包含失败消息。
建议: 该断言本身无意义,建议删除;如果保留,必须提供消息,例如 assertTrue("message", condition)。
- 🟡 `pmd:UnnecessaryBooleanAssertion` L81
assertTrue(true) 或类似语句是不必要的。
建议: 删除对布尔常量 true 的断言;若需要固定验证,应改为对实际被测状态的断言。
- 🟡 `pmd:UnitTestShouldUseBeforeAnnotation` L83
如果此方法用于测试初始化,请使用正确的注解。
建议: 在 JUnit Jupiter 中使用 @BeforeEach,在 JUnit 4 中使用 @Before,并补充初始化逻辑或删除空方法。
- 🟡 `pmd:DetachedTestCase` L83
可能是脱离的 JUnit 测试用例。
建议: 该方法名容易让 JUnit 误认为它是测试用例,但未使用生命周期注解;如果用于初始化,请添加 @BeforeEach/@Before;否则删除或重命名。
- 🟡 `pmd:PublicMemberInNonPublicType` L83
公共成员 'setUp' 声明在非公共类型中。
建议: 如果使用 JUnit Jupiter,可去掉 public 修饰;如果保留 JUnit 4,应将测试类声明为 public。
- 🟡 `pmd:AtLeastOneConstructor` L88
每个类都应声明至少一个构造函数。
建议: 为 MissingTestAnnotationTest 添加一个显式构造函数。
- 🟡 `pmd:TestClassWithoutTestCases` L88
类 'MissingTestAnnotationTest' 可能是测试类,但它不包含任何测试用例。
建议: 为该类添加一个带断言且标注 @Test 的测试方法;若只是 PMD 反例,可删除该类。
- 🟡 `pmd:PublicMemberInNonPublicType` L89
公共成员 'testSomething' 声明在非公共类型中。
建议: 如果使用 JUnit Jupiter,可去掉 public 修饰;如果保留 JUnit 4,应将测试类声明为 public。
- 🟡 `pmd:UnitTestShouldUseTestAnnotation` L89
单元测试应使用 @Test 注解,否则不会运行;在 JUnit Jupiter 中也可以使用 @RepeatedTest@TestFactory@TestTemplate@ParameterizedTest
建议: 在 testSomething 方法上添加 @org.junit.jupiter.api.Test(如果迁移到 Jupiter)或 org.junit.Test(如果保留 JUnit 4),并在方法内补充断言。
- 🟡 `pmd:AtLeastOneConstructor` L94
每个类都应声明至少一个构造函数。
建议: 为 SpellingTest 添加一个显式构造函数。
- 🟡 `pmd:TestClassWithoutTestCases` L94
类 'SpellingTest' 可能是测试类,但它不包含任何测试用例。
建议: 为 SpellingTest 补充真正的测试方法,并将 setup/teardown 改为带 @BeforeEach/@AfterEach 的 setUp/tearDown。
- 🟡 `pmd:PublicMemberInNonPublicType` L95
公共成员 'setup' 声明在非公共类型中。
建议: 如果使用 JUnit Jupiter,可去掉 public 修饰;如果保留 JUnit 4,应将测试类声明为 public。
- 🟡 `pmd:PublicMemberInNonPublicType` L97
公共成员 'teardown' 声明在非公共类型中。
建议: 如果使用 JUnit Jupiter,可去掉 public 修饰;如果保留 JUnit 4,应将测试类声明为 public。
- 🟡 `pmd:UseUtilityClass` L102
所有成员都是静态的。考虑添加私有无参构造函数以防止实例化。
建议: 如果 StaticSuiteTest 只是工具类,应添加私有无参构造器;如果它是测试套件,应改用 @RunWith(Suite.class) 与 @SuiteClasses 并删除静态 suite 方法。
- 🟡 `pmd:TestClassWithoutTestCases` L102
类 'StaticSuiteTest' 可能是测试类,但它不包含任何测试用例。
建议: 如果 StaticSuiteTest 是套件类,应添加套件注解并引用真实测试类;否则删除或补充测试方法。
- 🟡 `pmd:JUnit4SuitesShouldUseSuiteAnnotation` L103
JUnit 4 通过注解声明测试套件,而不是通过 suite 方法。
建议: 使用 @RunWith(Suite.class) 和 @SuiteClasses 声明测试套件并删除 suite();若迁移到 JUnit Platform Suite,应使用 @Suite 注解。
- 🟡 `pmd:PublicMemberInNonPublicType` L103
公共成员 'suite' 声明在非公共类型中。
建议: 如果保留 JUnit 4 suite 方法,应将该类声明为 public;如果使用注解套件,类同样应为 public。
- 🟡 `pmd:UseUtilityClass` L109
所有成员都是静态的。考虑添加私有无参构造函数以防止实例化。
建议: 如果 SuiteClassTest 只是工具类,应添加私有无参构造器;如果它是测试套件,应改用注解式套件并删除静态 suite 方法。
- 🟡 `pmd:TestClassWithoutTestCases` L109
类 'SuiteClassTest' 可能是测试类,但它不包含任何测试用例。
建议: 如果 SuiteClassTest 是套件类,应添加套件注解并引用真实测试类;否则删除或补充测试方法。
- 🟡 `pmd:JUnit4SuitesShouldUseSuiteAnnotation` L110
JUnit 4 通过注解声明测试套件,而不是通过 suite 方法。
建议: 使用 @RunWith(Suite.class) 和 @SuiteClasses 声明测试套件并删除 suite();若迁移到 JUnit Platform Suite,应使用 @Suite 注解。
- 🟡 `pmd:PublicMemberInNonPublicType` L110
公共成员 'suite' 声明在非公共类型中。
建议: 如果保留 JUnit 4 suite 方法,应将该类声明为 public;如果使用注解套件,类同样应为 public。
AI 审查 · 7 条建议
- 🔴 [AI] [bug] `assertEquals-argument-order` L43
**assertEquals 参数顺序颠倒,导致失败消息误导**
第 43 行调用 Assert.assertEquals(actual, expected),把 actual 放在了 expected 参数位置。JUnit 的 assertEquals 期望第一个参数是 expected、第二个是 actual;当前写法在断言失败时会输出与实际相反的消息,且语义错误。
建议: 改为 assertEquals("expected should equal actual", expected, actual),并尽量给断言补充消息;若使用 JUnit Jupiter,应为 Assertions.assertEquals(expected, actual)。
- 🔴 [AI] [bug] `suite-returns-null` L104
**StaticSuiteTest.suite() 返回 null,测试套件运行时会触发空指针**
StaticSuiteTest.suite() 直接返回 null。JUnit 执行套件时会尝试遍历返回的 Test 对象,导致 NullPointerException。
建议: 删除 suite() 方法,改用 @RunWith(Suite.class) 和 @SuiteClasses({...});若保留 suite(),请返回非 null 的 TestSuite。
- 🔴 [AI] [bug] `suite-returns-null` L111
**SuiteClassTest.suite() 返回 null,测试套件运行时会触发空指针**
SuiteClassTest.suite() 直接返回 null。JUnit 执行套件时会尝试遍历返回的 Test 对象,导致 NullPointerException。
建议: 删除 suite() 方法,改用 @RunWith(Suite.class) 和 @SuiteClasses({...});若保留 suite(),请返回非 null 的 TestSuite。
- 🟡 [AI] [design] `junit4-assert-usage` L7
**迁移到 JUnit Jupiter 后仍使用 JUnit 4 的 Assert API**
代码中仍导入并使用 org.junit.Assert(如 Assert.assertTrue、Assert.assertEquals、Assert.fail)。在 JUnit Jupiter 下应使用 org.junit.jupiter.api.Assertions,否则断言行为/异常类型与 JUnit 5 不一致,且容易造成依赖混乱。
建议: 将导入改为 import org.junit.jupiter.api.Assertions;,并把所有 Assert. 调用改为 Assertions.(或使用静态导入);同时确认 @Test 导入来自 org.junit.jupiter.api。
- 🟡 [AI] [design] `tautological-assertions` L31
**testTooMany 中的 assertEquals 只比较常量与自身,属于恒真断言**
第 31-35 行的 assertEquals(1, 1)、(2, 2) 等断言只比较常量与自身,即使被测逻辑被删除或出错,测试也会通过。该类断言没有测试价值。
建议: 删除这些无意义断言,改为对被测逻辑设置明确的输入和预期输出;若只是 PMD 演示反例,可在注释中说明。
- 🟡 [AI] [bug] `test-class-visibility` L68
**多个测试类不是 public,若按 JUnit 4 运行将无法发现用例**
MissingAfterTest、MissingBeforeTest、MissingTestAnnotationTest、SpellingTest、StaticSuiteTest、SuiteClassTest 均为包级私有类。当前代码仍混用 JUnit 4 API,若按 JUnit 4 运行,非 public 测试类不会被识别;若按 JUnit Jupiter 运行,又需要先彻底移除 JUnit 4 API。
建议: 统一迁移到 JUnit Jupiter 并将测试类/方法改为包级私有,或保留 JUnit 4 并将所有测试类及测试方法声明为 public。
- 🟡 [AI] [design] `junit-lifecycle-naming` L95
**setup/teardown 拼写不符合 JUnit 生命周期方法命名**
SpellingTest 中 setup() 和 teardown() 缺少大写字母 P/D,JUnit 不会将它们识别为生命周期方法;若意图是初始化/清理,应命名为 setUp/tearDown 并添加 @BeforeEach/@AfterEach
建议: 改为 public void setUp() 并加 @BeforeEachpublic void tearDown() 并加 @AfterEach;同时为类添加真正的 @Test 方法。
@@ -0,0 +1,55 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\JUnit5ArgOrderTest.java`
**语言:** java
**耗时:** 94.8s
**分析工具:** pmd
---
总计: 12 | 错误: 2 | 警告: 8 | 建议: 2
静态分析 · 9 个问题
- 🔴 `pmd:SystemPrintln` L24
使用了 System.out / System.err。
建议: 移除该输出语句,或改用日志框架(如 java.util.logging、SLF4J)进行记录。
- 🟡 `pmd:AtLeastOneConstructor` L10
每个类都应声明至少一个构造函数。
建议: 为类添加一个显式的构造函数,例如:`public JUnit5ArgOrderTest() {}`,或确保存在其他构造函数。
- 🟡 `pmd:JUnitJupiterTestShouldBePackagePrivate` L10
JUnit 5 测试类应为包私有(不要使用 public 修饰符)。
建议: 将 `public class JUnit5ArgOrderTest` 改为 `class JUnit5ArgOrderTest`,使测试类为包私有。
- 🟡 `pmd:JUnitJupiterTestShouldBePackagePrivate` L12
JUnit 5 测试方法应为包私有(不要使用 public 修饰符)。
建议: 将 `public void testX()` 改为 `void testX()`
- 🟡 `pmd:LocalVariableCouldBeFinal` L13
局部变量 `actual` 可以声明为 final。
建议: 在变量声明处添加 `final` 修饰符:`final String actual = next("foo");`
- 🟡 `pmd:AssertEqualsArgumentOrder` L14
此 assertEquals() 调用的 expected 和 actual 参数顺序颠倒了。
建议: 将期望值作为第一个参数,实际值作为第二个参数:`assertEquals("bar", actual);`
- 🟡 `pmd:UnitTestAssertionsShouldIncludeMessage` L14
单元测试断言应包含一个描述性消息。
建议: 为断言添加消息参数:`assertEquals(expected, actual, "消息内容");`,例如 `assertEquals("bar", actual, "next() 的返回值应等于 bar");`
- 🟡 `pmd:CommentDefaultAccessModifier` L17
方法 `next(String)` 缺少默认访问修饰符(包私有)的注释。
建议: 在方法前添加注释 `/* package */`,或者显式声明访问修饰符(如 `private`)。
- 🟡 `pmd:MethodArgumentCouldBeFinal` L17
参数 `s` 未被赋值,可以声明为 final。
建议: 在参数类型前添加 `final``String next(final String s)`
AI 审查 · 3 条建议
- 🔴 [AI] [bug] `wrong-test-expectation` L14
**测试断言期望值与实际输入不匹配**
`next("foo")` 返回 `"foo"`(因为 `next` 直接返回参数),但断言期望值为 `"bar"`。即使把 assertEquals 参数顺序调整正确,`assertEquals("bar", actual)` 仍会失败,因为 `actual``"foo"`。请检查测试意图:要么将期望值改为 `"foo"`,要么让 `next` 方法产生 `"bar"` 作为结果。
建议: 如果 `next` 被设计为恒等函数,应将断言改为 `assertEquals("foo", actual)`;否则修改 `next` 的实现以返回预期值。
- 🔵 [AI] [design] `method-can-be-static` L17
**辅助方法可声明为 static**
`next(String)` 不访问任何实例字段或实例方法,应声明为 `static`,以更清晰地表达其无状态性,并避免实例持有。
建议: 将 `String next(String s)` 改为 `static String next(String s)`;调用处 `next("foo")` 在实例方法内仍可调用静态方法,无需修改。
- 🔵 [AI] [design] `top-level-class-in-test-file` L22
**测试文件中不应包含无关的顶层类**
`Junit5Main` 是一个独立的顶层类,包含 `main` 方法,却与测试类 `JUnit5ArgOrderTest` 放在同一个源文件中。这样会降低可读性,并可能导致构建工具扫描到非测试类。建议将 `Junit5Main` 移到单独的 `Junit5Main.java` 文件中。
建议: 将 `Junit5Main` 类移到独立文件,或将其从测试源集中移除。
@@ -0,0 +1,63 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\JUnit5RulesTest.java`
**语言:** java
**耗时:** 139.8s
**分析工具:** pmd
---
总计: 14 | 错误: 2 | 警告: 11 | 建议: 1
静态分析 · 9 个问题
- 🔴 `pmd:SystemPrintln` L25
使用了 System.out/err 输出。
建议: 避免直接使用 System.out.println,建议使用日志框架(如 SLF4J/Log4j2)或 java.util.logging.Logger。例如:private static final Logger LOG = Logger.getLogger(JupiterMain.class.getName()); LOG.info("demo jupiter");
- 🟡 `pmd:AtLeastOneConstructor` L9
每个类都应至少声明一个构造函数。
建议: 为类添加一个无参构造函数。由于当前是测试类,可添加 public JupiterPublicTest() {} 以消除警告。
- 🟡 `pmd:JUnitJupiterTestShouldBePackagePrivate` L9
JUnit 5 测试类应为包私有。
建议: 移除 public 修饰符,将 'public class JupiterPublicTest' 改为 'class JupiterPublicTest'。
- 🟡 `pmd:JUnitJupiterTestShouldBePackagePrivate` L11
JUnit 5 测试方法应为包私有。
建议: 移除 public 修饰符,将 'public void testPublic()' 改为 'void testPublic()'。
- 🟡 `pmd:UnitTestShouldIncludeAssert` L11
该单元测试应包含 assert() 或 fail() 断言。
建议: 在测试方法体中添加断言,例如:org.junit.jupiter.api.Assertions.assertTrue(true)。如果测试业务逻辑,请断言实际返回值或状态。
- 🟡 `pmd:AtLeastOneConstructor` L16
每个类都应至少声明一个构造函数。
建议: 为 JupiterPrivateTest 类添加一个包私有无参构造函数,例如:JupiterPrivateTest() {}
- 🟡 `pmd:UnusedPrivateMethod` L18
避免使用未使用的私有方法 'testPrivate()'。
建议: testPrivate 是私有方法且未被使用,但又标注了 @Test。建议将其改为包私有方法(移除 private),使其成为有效的测试方法;如果它是普通辅助方法,则应在类内调用或删除。
- 🟡 `pmd:JUnitJupiterTestNoPrivateModifier` L18
JUnit 测试方法不能是 private。
建议: 删除 private 修饰符,改为包私有:private void testPrivate() 改为 void testPrivate()。注意:私有测试方法会导致 JUnit 执行失败,而不是被忽略。
- 🟡 `pmd:UnitTestShouldIncludeAssert` L18
该单元测试应包含 assert() 或 fail() 断言。
建议: 在 testPrivate 方法中加入断言,例如:org.junit.jupiter.api.Assertions.assertTrue(true)。同时建议将方法改为包私有。
AI 审查 · 5 条建议
- 🔴 [AI] [bug] `main-class-must-be-public` L23
**主类 JupiterMain 不是 public,无法作为程序入口**
Java 应用程序入口要求主类是 public(且 main 方法为 public static void)。JupiterMain 为包私有类,使用 java JupiterMain 启动时 JVM 会报找不到 main 方法。若该类仅用于演示,也应提取为独立 public 类。
建议: 将 JupiterMain 提取到独立文件 JupiterMain.java,并将类声明改为 public class JupiterMain。当前文件中已有一个 public 类 JupiterPublicTest,不能同时存在两个 public 顶层类。
- 🟡 [AI] [design] `one-top-level-class-per-file` L9
**同一文件包含多个顶层类,降低可维护性**
该文件中同时定义了 JupiterPublicTest、JupiterPrivateTest 和 JupiterMain 三个顶层类。虽然 Java 允许在一个 .java 文件中声明多个非 public 顶层类,但实践上每个类应单独一个文件,以提升可读性和可维护性,并避免外部包导入时的困惑。
建议: 将每个顶层类分别放入独立的 .java 文件中,并确保 public 类的文件名与其类名一致。
- 🟡 [AI] [style] `class-naming-misleading` L16
**类名 JupiterPrivateTest 与可见性语义不符**
Java 顶层类不能为 private。JupiterPrivateTest 实际是包私有类,但类名容易让人误以为它是 private;该类中的测试方法也恰好是 private,进一步造成混淆。
建议: 将类改名为 JupiterPackagePrivateTest 或类似不含 private 的名称,同时将私有测试方法改为包私有。
- 🟡 [AI] [bug] `misleading-comment-junit-private` L18
**注释称私有测试方法不会执行,与 JUnit 5 实际行为不符**
代码注释写着 'private 测试方法,不会执行',但 JUnit Jupiter 的 @Test 方法声明为 private 时,JUnit 会在运行时报告测试失败(JUnitException),而不是忽略。这种错误注解会误导开发者。
建议: 更新注释为准确描述,并将测试方法改为包私有,确保其被 JUnit 执行。
- 🔵 [AI] [style] `test-method-naming` L11
**测试方法名 testPublic 不具描述性**
测试方法名仅表达了'公开',未反映被测试的行为或预期结果。好的测试命名应说明场景和预期,例如 shouldReturnXWhenY。
建议: 将方法重命名为更具行为描述性的名称,例如 shouldReturnExpectedValue()。
+146
View File
@@ -0,0 +1,146 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\jsp\JspFix.jsp`
**语言:** html
**耗时:** 204.4s
**分析工具:** jsp
---
总计: 42 | 错误: 6 | 警告: 36 | 建议: 0
静态分析 · 38 个问题
- 🔴 `pmd:NoLongScripts` L8
第 8 行:避免在 JSP 文件中包含较长的脚本(如 JavaScript)。
建议: 将 JavaScript 移至外部文件,创建 js/demo.js 并放入两个函数,用 <script src="js/demo.js"></script> 替换整个内联 <script> 块。
- 🔴 `eslint:no-var` L10
第 10 行:不应使用 var,请改用 let 或 const。
建议: total 在循环中会被修改,建议改为 let total = 0;。
- 🔴 `eslint:no-var` L11
第 11 行:不应使用 var,请改用 let 或 const。
建议: 循环变量应使用块级作用域,建议改为 let i = 0;。
- 🔴 `eslint:no-unused-vars` L16
第 16 行:'doMore' 已定义但从未使用。
建议: 删除 doMore 函数;如果后续需要 doStuff,可保留 doStuff 并从外部调用。
- 🔴 `pmd:NoHtmlComments` L23
第 23 行:请使用 JSP 注释代替 HTML 注释。
建议: 将 HTML 注释 <!-- this is an html comment --> 改为 JSP 注释 <%-- this is an html comment --%>,避免注释内容发送到浏览器。
- 🟡 `pmd:JspEncoding` L1
第 1 行:JSP 文件应使用 UTF-8 编码。
建议: 在 page 指令中添加 pageEncoding="UTF-8",并将 contentType 设置为 text/html; charset=UTF-8。
- 🟡 `pmd:NoInlineScript` L8
第 8 行:不应内联 HTML 脚本内容。
建议: 不要在内联 <script> 中写脚本;将脚本抽取到外部 JS 文件后通过 src 引入,避免内联脚本并降低 CSP 风险。
- 🟡 `pmd:NoScriptlets` L26
第 26 行:避免在 JSP 文件中使用 scriptletJava 代码片段)。
建议: 将业务逻辑移入 Servlet/后端;若当前只需输出 1+2 的结果,可直接使用 EL 表达式 ${1 + 2} 替代整个 scriptlet。
- 🟡 `pmd:LocalVariableCouldBeFinal` L27
第 27 行:局部变量 'x' 可声明为 final。
建议: 变量 x 声明后未再赋值,改为 final int x = 1;。
- 🟡 `pmd:LocalVariableCouldBeFinal` L28
第 28 行:局部变量 'y' 可声明为 final。
建议: 变量 y 声明后未再赋值,改为 final int y = 2;。
- 🟡 `pmd:LocalVariableCouldBeFinal` L29
第 29 行:局部变量 'z' 可声明为 final。
建议: 变量 z 声明后未再赋值,改为 final int z = x + y;。
- 🟡 `pmd:NoJspForward` L33
第 33 行:不要从 JSP 文件内部执行转发。
建议: 将转发逻辑移到 Servlet 或 Filter 中,使用 request.getRequestDispatcher("other.jsp").forward(request, response)JSP 应只承担视图渲染。
- 🟡 `pmd:NoScriptlets` L35
第 35 行:避免在 JSP 文件中使用 scriptletJava 代码片段)。
建议: 该 scriptlet 中大量变量未被使用,仅依赖 xx + yy 的输出;应删除整个 scriptlet,直接用 EL 表达式 ${24 + 25} 输出结果。
- 🟡 `pmd:UnusedLocalVariable` L36
第 36 行:应避免未使用的局部变量 'a'。
建议: 删除未使用的局部变量 a。
- 🟡 `pmd:UnusedLocalVariable` L37
第 37 行:应避免未使用的局部变量 'b'。
建议: 删除未使用的局部变量 b。
- 🟡 `pmd:UnusedLocalVariable` L38
第 38 行:应避免未使用的局部变量 'c'。
建议: 删除未使用的局部变量 c。
- 🟡 `pmd:UnusedLocalVariable` L39
第 39 行:应避免未使用的局部变量 'd'。
建议: 删除未使用的局部变量 d。
- 🟡 `pmd:UnusedLocalVariable` L40
第 40 行:应避免未使用的局部变量 'e'。
建议: 删除未使用的局部变量 e。
- 🟡 `pmd:UnusedLocalVariable` L41
第 41 行:应避免未使用的局部变量 'f'。
建议: 删除未使用的局部变量 f。
- 🟡 `pmd:UnusedLocalVariable` L42
第 42 行:应避免未使用的局部变量 'g'。
建议: 删除未使用的局部变量 g。
- 🟡 `pmd:UnusedLocalVariable` L43
第 43 行:应避免未使用的局部变量 'h'。
建议: 删除未使用的局部变量 h。
- 🟡 `pmd:UnusedLocalVariable` L44
第 44 行:应避免未使用的局部变量 'i2'。
建议: 删除未使用的局部变量 i2。
- 🟡 `pmd:UnusedLocalVariable` L45
第 45 行:应避免未使用的局部变量 'j2'。
建议: 删除未使用的局部变量 j2。
- 🟡 `pmd:UnusedLocalVariable` L46
第 46 行:应避免未使用的局部变量 'k'。
建议: 删除未使用的局部变量 k。
- 🟡 `pmd:UnusedLocalVariable` L47
第 47 行:应避免未使用的局部变量 'l'。
建议: 删除未使用的局部变量 l。
- 🟡 `pmd:UnusedLocalVariable` L48
第 48 行:应避免未使用的局部变量 'm'。
建议: 删除未使用的局部变量 m。
- 🟡 `pmd:UnusedLocalVariable` L49
第 49 行:应避免未使用的局部变量 'n'。
建议: 删除未使用的局部变量 n。
- 🟡 `pmd:UnusedLocalVariable` L50
第 50 行:应避免未使用的局部变量 'o'。
建议: 删除未使用的局部变量 o。
- 🟡 `pmd:UnusedLocalVariable` L51
第 51 行:应避免未使用的局部变量 'p'。
建议: 删除未使用的局部变量 p。
- 🟡 `pmd:UnusedLocalVariable` L52
第 52 行:应避免未使用的局部变量 'q'。
建议: 删除未使用的局部变量 q。
- 🟡 `pmd:UnusedLocalVariable` L53
第 53 行:应避免未使用的局部变量 'r'。
建议: 删除未使用的局部变量 r。
- 🟡 `pmd:UnusedLocalVariable` L54
第 54 行:应避免未使用的局部变量 's2'。
建议: 删除未使用的局部变量 s2。
- 🟡 `pmd:UnusedLocalVariable` L55
第 55 行:应避免未使用的局部变量 't'。
建议: 删除未使用的局部变量 t。
- 🟡 `pmd:UnusedLocalVariable` L56
第 56 行:应避免未使用的局部变量 'u'。
建议: 删除未使用的局部变量 u。
- 🟡 `pmd:UnusedLocalVariable` L57
第 57 行:应避免未使用的局部变量 'v'。
建议: 删除未使用的局部变量 v。
- 🟡 `pmd:UnusedLocalVariable` L58
第 58 行:应避免未使用的局部变量 'w'。
建议: 删除未使用的局部变量 w。
- 🟡 `pmd:LocalVariableCouldBeFinal` L59
第 59 行:局部变量 'xx' 可声明为 final。
建议: 变量 xx 声明后未再赋值,改为 final int xx = 24;。
- 🟡 `pmd:LocalVariableCouldBeFinal` L60
第 60 行:局部变量 'yy' 可声明为 final。
建议: 变量 yy 声明后未再赋值,改为 final int yy = 25;。
AI 审查 · 4 条建议
- 🔴 [AI] [bug] `output-before-forward` L33
**jsp:forward 之前已经输出响应内容,可能导致转发失败**
第 23-31 行产生的 HTML 注释、div 和 out.println 输出都会先写入响应缓冲区;随后第 33 行才执行 <jsp:forward>。若缓冲区在转发前被提交,容器会抛出 IllegalStateException;即使未提交,之前输出也可能被丢弃或导致预期外的页面行为。
建议: 不要在 JSP 中直接做转发。将前置判断与转发逻辑放到 Servlet/Filter 中,通过 RequestDispatcher 转发;如果必须在 JSP 中处理,应确保转发发生在任何输出之前。
- 🟡 [AI] [design] `dead-inline-script` L8
**整段内联脚本为死代码**
第 8-19 行的 <script> 中,doMore 未被任何地方调用,doStuff 只被 doMore 引用;如果没有外部脚本通过全局函数名调用这两个函数,整段脚本实际不可达。静态检查只报告了 doMore 未使用,未指出 doStuff 也随之为死代码。
建议: 确认无外部引用后删除整个 <script> 块;如果功能在未来需要使用,应抽取到外部 JS 文件再按需引入。
- 🟡 [AI] [security] `inline-style-csp` L24
**内联 style 属性削弱内容安全策略(CSP)**
第 24 行使用 style="background-color: #f00;" 内联样式。若站点部署 CSP style-src,内联样式可能被阻止或被迫放宽策略;同时硬编码颜色难以复用和维护。
建议: 在外部样式表或页面 <style> 中定义 .error-block { background-color: #f00; },页面使用 <div class="error-block">。
- 🟡 [AI] [security] `unescaped-scriptlet-output` L30
**scriptlet 直接输出表达式,缺少 HTML 转义**
第 30 行 out.println(z)(以及第 61 行的 out.println(xx + yy))直接将表达式写入响应。当前值是常量,但若这些位置掺入任何用户可控值,会形成反射型/存储型 XSS;JSP scriptlet 不会自动转义。
建议: 优先使用 JSTL <c:out> 输出;若暂时保留 scriptlet,应使用 OWASP Java Encoder 等工具对输出编码,例如 Encode.forHtml(String.valueOf(z))。
@@ -0,0 +1,61 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\LoggerDemo.java`
**语言:** java
**耗时:** 109.8s
**分析工具:** pmd
---
总计: 14 | 错误: 3 | 警告: 10 | 建议: 1
静态分析 · 11 个问题
- 🔴 `pmd:FieldNamingConventions` L11
第11行:字段名 'LOG' 不符合命名规范 '[a-z][a-zA-Z0-9]*'。
建议: 将字段名从大写 `LOG` 改为小驼峰 `log`,例如:`protected Log log = LogFactory.getLog(BadLogger.class);`
- 🔴 `pmd:FieldNamingConventions` L16
第16行:常量名 '_LOG' 不符合命名规范 '[A-Z][A-Z_0-9]*'。
建议: 将常量名 `_LOG` 改为全大写形式 `LOG`,并同步更新所有引用(如第21行的 `_LOG.error`)。
- 🔴 `pmd:SystemPrintln` L30
第30行:在代码中使用了 System.out/err。
建议: 应使用日志框架替代 `System.out.println`,例如:`LogFactory.getLog(LoggerMain.class).info("demo logger");`,以便统一管理日志输出和级别。
- 🟡 `pmd:AtLeastOneConstructor` L10
第10行:每个类应至少声明一个构造器。
建议: 请为 BadLogger 类添加显式构造器,例如 `public BadLogger() {}`。如果该类设计为不可实例化的工具类,则声明私有构造器。
- 🟡 `pmd:ProperLogger` L11
第11行:Logger 应定义为 private static final,并使用正确的类。
建议: 将 logger 字段修改为 `private static final Log LOG = LogFactory.getLog(BadLogger.class);`,确保字段是私有的、静态的、final 的且类型参数为当前类。
- 🟡 `pmd:AtLeastOneConstructor` L15
第15行:每个类应至少声明一个构造器。
建议: 为 CorrectExceptionLog 类添加显式构造器,例如 `public CorrectExceptionLog() {}`,或如果不需要实例化则声明为 private。
- 🟡 `pmd:ProperLogger` L16
第16行:Logger 应定义为 private static final,并使用正确的类。
建议: 将 `_LOG` 字段重命名为 `LOG`,并确保声明为 `private static final Log LOG = LogFactory.getLog(CorrectExceptionLog.class);`
- 🟡 `pmd:CommentDefaultAccessModifier` L17
第17行:方法 'bar()' 缺少默认访问修饰符的注释。
建议: 为包级私有方法添加注释 `/* package */`,或显式声明 `public``protected``private` 修饰符。
- 🟡 `pmd:AvoidCatchingGenericException` L20
第20行:避免在 try-catch 块中捕获 Exception 这类通用异常。
建议: 应改为捕获可能抛出的具体异常类型(如 `IllegalStateException`),或使用多 `catch` 分别处理不同的特定异常,避免使用 `catch (Exception e)`
- 🟡 `pmd:UseCorrectExceptionLogging` L21
第21行:记录异常时使用了不正确的日志语句。
建议: 应使用带消息和异常对象的重载方法,例如 `_LOG.error("Failed to do work", e);`,确保异常堆栈被记录。
- 🟡 `pmd:CommentDefaultAccessModifier` L24
第24行:方法 'doWork()' 缺少默认访问修饰符的注释。
建议: 为包级私有方法添加注释 `/* package */`,或显式声明访问修饰符。
AI 审查 · 3 条建议
- 🟡 [AI] [bug] `exception-swallowed` L20
**捕获异常后仅记录日志,未进行任何错误处理**
在 CorrectExceptionLog.bar() 中,catch 块捕获所有 Exception 后仅调用 _LOG.error(e) 记录日志,没有恢复、补偿或重新抛出异常。这会导致异常被静默吞没,调用方无法感知失败,程序可能继续在错误状态下运行,掩盖潜在缺陷。
建议: 根据业务场景处理异常:如果可恢复,则执行补偿逻辑;如果不可恢复,应记录日志后重新抛出,或在方法签名中声明抛出。推荐改为 `catch (Exception e) { log.error("Failed to do work", e); throw new RuntimeException(e); }`,并尽可能捕获更具体的异常类型。
- 🟡 [AI] [bug] `empty-method` L24
**doWork() 方法为空实现,调用无效果**
CorrectExceptionLog.doWork() 方法体为空,未执行任何操作。若 bar() 调用它,会静默成功但不产生任何效果,容易让调用方误以为工作已完成,属于不完整实现或占位代码。
建议: 实现 doWork() 的具体业务逻辑;如果尚未完成,应抛出 UnsupportedOperationException 或添加明确的 TODO 注释,避免静默空转。
- 🔵 [AI] [design] `utility-class-instantiable` L28
**入口类 LoggerMain 缺少私有构造器,可被实例化**
LoggerMain 是仅包含 main 方法的入口类,默认公有构造器使其可以被外部实例化,产生无意义的对象,暴露不必要的 API 并可能造成混淆。
建议: 为 LoggerMain 添加私有构造器,阻止实例化:`private LoggerMain() { throw new AssertionError("Utility class"); }`
@@ -0,0 +1,37 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\design\extra\LoosePackageCouplingDemo.java`
**语言:** java
**耗时:** 142.8s
**分析工具:** pmd
---
总计: 6 | 错误: 0 | 警告: 5 | 建议: 1
静态分析 · 3 个问题
- 🟡 `pmd:AtLeastOneConstructor` L12
每个类应至少声明一个构造函数。
建议: 请为 LoosePackageCouplingDemo 类显式添加构造函数,例如添加一个包私有构造函数:LoosePackageCouplingDemo() { /* 显式默认构造 */ };若类为工具类,可改为 private。
- 🟡 `pmd:CommentDefaultAccessModifier` L13
方法“bad()”缺少注释默认访问修饰符。
建议: 在方法声明前注释默认访问级别,例如:/* default */ void bad() { ... };或显式使用 private(仅内部使用)或 public(对外 API),避免隐式包私有。
- 🟡 `pmd:LocalVariableCouldBeFinal` L14
局部变量“svc”应声明为 final。
建议: 将声明改为 final ApiService svc = new ApiService();,明确该引用初始化后不再发生变化。
AI 审查 · 3 条建议
- 🟡 [AI] [design] `dead-code` L13
**bad() 方法在当前包中从未被调用,属于死代码**
整个文件中没有其他代码调用 bad(),且 bad() 为包私有方法,当前同包其他类也未使用,说明该方法可能是未完成的演示残留或调用入口缺失。死代码会增加维护面积,并掩盖真实的业务行为。
建议: 若该方法无业务入口,应删除;若需要保留作为演示,可添加一个 main 方法或单元测试入口,并让方法名表达实际用途。
- 🟡 [AI] [design] `package-coupling` L14
**extra 包直接依赖 api 包的具体实现,导致包间强耦合**
LoosePackageCouplingDemo 位于 com.demo.design.extra 包,却直接 import 并 new 了 com.demo.api.ApiService。这样将 extra 包的实现与 api 包的具体类型绑定在一起,未来 ApiService 的构造函数或生命周期变化会波及此处;若存在多个类似调用点,重构成本更高。代码注释也表明这是 LoosePackageCoupling 规则的演示,但规则未被配置执行,因此该耦合在质量门禁中不会暴露。
建议: 为 extra 包引入抽象接口(例如 ApiClient),只依赖接口完成调用,并通过构造函数注入 ApiService(或由工厂提供),避免在业务代码中直接 new 具体类;同时将 LoosePackageCoupling 规则在 PMD ruleset 中配置 packages/classes 后启用,以持续检查包耦合。
- 🔵 [AI] [style] `unclear-method-name` L13
**方法名 bad() 无法表达方法职责**
bad() 是一个无意义的命名,读者无法从名称中得知该方法执行何种具体操作。良好的方法名应以动词开头体现行为,例如 doWork、sendRequest 等。
建议: 将 bad() 重命名为具有业务含义的动词短语;如果只是示例,建议改为 demoApiCall() 等更贴近用途的名字。
@@ -0,0 +1,398 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\mtps\MultiPerfSecurity.java`
**语言:** java
**耗时:** 301.2s
**分析工具:** pmd
> ⚠️ 部分 AI 功能不可用,报告已降级
## 错误
- AI 审查请求失败: AbortError: This operation was aborted
---
总计: 190 | 错误: 7 | 警告: 175 | 建议: 8
静态分析 · 190 个问题
- 🔴 `pmd:DoubleCheckedLocking` L58
Double checked locking is not thread safe in Java.
- 🔴 `pmd:FieldNamingConventions` L111
The constant name 'sdf' doesn't match '[A-Z][A-Z_0-9]*'
- 🔴 `pmd:AvoidFileStream` L157
Avoid instantiating FileInputStream, FileOutputStream, FileReader, or FileWriter
- 🔴 `pmd:StringInstantiation` L232
Avoid instantiating String objects; this is usually unnecessary.
- 🔴 `pmd:AvoidReassigningParameters` L268
Avoid reassigning parameters such as 's'
- 🔴 `pmd:SystemPrintln` L300
Usage of System.out/err
- 🔴 `pmd:SystemPrintln` L382
Usage of System.out/err
- 🟡 `pmd:AtLeastOneConstructor` L31
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateField` L32
Avoid unused private fields such as 'count'.
- 🟡 `pmd:PublicMemberInNonPublicType` L33
Public member 'incr' declared in a non-public type
- 🟡 `pmd:AvoidSynchronizedAtMethodLevel` L33
Use block level locking rather than method level synchronization
- 🟡 `pmd:AtLeastOneConstructor` L39
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L40
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L41
Local variable 'g' could be declared final
- 🟡 `pmd:AvoidThreadGroup` L41
Avoid using java.lang.ThreadGroup; it is not thread safe
- 🟡 `pmd:UnusedLocalVariable` L42
Avoid unused local variables such as 't'.
- 🟡 `pmd:AtLeastOneConstructor` L47
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L48
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L49
Local variable 't' could be declared final
- 🟡 `pmd:UseUtilityClass` L55
All members are static. Consider adding a private no-args constructor to prevent instantiation.
- 🟡 `pmd:CommentDefaultAccessModifier` L58
Missing commented default access modifier on method 'get()'
- 🟡 `pmd:UseUtilityClass` L71
All members are static. Consider adding a private no-args constructor to prevent instantiation.
- 🟡 `pmd:CommentDefaultAccessModifier` L74
Missing commented default access modifier on method 'get()'
- 🟡 `pmd:NonThreadSafeSingleton` L75
Singleton is not thread safe
- 🟡 `pmd:AtLeastOneConstructor` L83
Each class should declare at least one constructor
- 🟡 `pmd:OverridingThreadRun` L85
Don't override Thread.run() method, use Runnable instead
- 🟡 `pmd:UnusedPrivateField` L91
Avoid unused private fields such as 'SDF'.
- 🟡 `pmd:SimpleDateFormatNeedsLocale` L91
When instantiating a SimpleDateFormat object, specify a Locale
- 🟡 `pmd:AtLeastOneConstructor` L95
Each class should declare at least one constructor
- 🟡 `pmd:UseConcurrentHashMap` L96
If you run in Java5 or newer and have concurrent access, you should use the ConcurrentHashMap implementation
- 🟡 `pmd:CommentDefaultAccessModifier` L96
Missing commented default access modifier on field 'map'
- 🟡 `pmd:AtLeastOneConstructor` L100
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L101
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L102
Local variable 'lock' could be declared final
- 🟡 `pmd:UseNotifyAllInsteadOfNotify` L104
Call Thread.notifyAll() rather than Thread.notify()
- 🟡 `pmd:AtLeastOneConstructor` L110
Each class should declare at least one constructor
- 🟡 `pmd:SimpleDateFormatNeedsLocale` L111
When instantiating a SimpleDateFormat object, specify a Locale
- 🟡 `pmd:CommentDefaultAccessModifier` L113
Missing commented default access modifier on method 'bar()'
- 🟡 `pmd:UnsynchronizedStaticFormatter` L114
Static Formatter objects should be accessed in a synchronized manner
- 🟡 `pmd:ReplaceJavaUtilDate` L114
Usage of java.util.Date should be replaced with classes from java.time
- 🟡 `pmd:AtLeastOneConstructor` L123
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L124
Missing commented default access modifier on method 'bad(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L124
Parameter 'x' is not assigned and could be declared final
- 🟡 `pmd:AddEmptyString` L125
Do not add empty strings
- 🟡 `pmd:AtLeastOneConstructor` L130
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L131
Missing commented default access modifier on method 'bad(StringBuffer)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L131
Parameter 'sb' is not assigned and could be declared final
- 🟡 `pmd:AppendCharacterWithChar` L132
Avoid appending characters as strings in StringBuffer.append.
- 🟡 `pmd:AtLeastOneConstructor` L137
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L138
Missing commented default access modifier on method 'bad(int[], int[])'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L138
Parameter 'src' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L138
Parameter 'dst' is not assigned and could be declared final
- 🟡 `pmd:AvoidArrayLoops` L139
Arrays.copyOf or System.arraycopy are more efficient
- 🟡 `pmd:AtLeastOneConstructor` L146
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L147
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L148
Local variable 'c' could be declared final
- 🟡 `pmd:ReplaceJavaUtilCalendar` L148
Usage of java.util.Calendar should be replaced with classes from java.time
- 🟡 `pmd:UselessPureMethodCall` L150
Do not call pure method getTime if the result is not used.
- 🟡 `pmd:AtLeastOneConstructor` L155
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L156
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:CloseResource` L157
Ensure that resources like this FileInputStream object are closed after use
- 🟡 `pmd:LocalVariableCouldBeFinal` L157
Local variable 'fis' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L164
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L165
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UnusedLocalVariable` L167
Avoid unused local variables such as 'o'.
- 🟡 `pmd:AvoidInstantiatingObjectsInLoops` L167
Avoid instantiating new objects inside loops
- 🟡 `pmd:AtLeastOneConstructor` L173
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L174
Missing commented default access modifier on field 'b'
- 🟡 `pmd:BigIntegerInstantiation` L174
Don't create instances of already existing BigInteger and BigDecimal (ZERO, ONE, TEN)
- 🟡 `pmd:AtLeastOneConstructor` L178
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L179
Missing commented default access modifier on method 'bad(StringBuilder)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L179
Parameter 'sb' is not assigned and could be declared final
- 🟡 `pmd:ConsecutiveAppendsShouldReuse` L180
StringBuffer (or StringBuilder).append is called consecutively without reusing the target variable.
- 🟡 `pmd:ConsecutiveLiteralAppends` L180
StringBuffer (or StringBuilder).append is called 3 consecutive times with literals. Use a single append with a single combined String.
- 🟡 `pmd:ConsecutiveAppendsShouldReuse` L181
StringBuffer (or StringBuilder).append is called consecutively without reusing the target variable.
- 🟡 `pmd:AppendCharacterWithChar` L181
Avoid appending characters as strings in StringBuffer.append.
- 🟡 `pmd:AtLeastOneConstructor` L187
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L188
Missing commented default access modifier on method 'bad(StringBuilder)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L188
Parameter 'sb' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L194
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L195
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L195
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:LiteralsFirstInComparisons` L196
Position literals first in String comparisons
- 🟡 `pmd:AtLeastOneConstructor` L201
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L202
Missing commented default access modifier on method 'bad(int, int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L202
Parameter 'a' is not assigned and could be declared final
- 🟡 `pmd:MethodArgumentCouldBeFinal` L202
Parameter 'b' is not assigned and could be declared final
- 🟡 `pmd:VariableCanBeInlined` L203
Consider simply using the value vs. storing it in local variable 's'.
- 🟡 `pmd:LocalVariableCouldBeFinal` L203
Local variable 's' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L209
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L210
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L210
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:LocalVariableCouldBeFinal` L211
Local variable 'sb' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L217
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L218
Missing commented default access modifier on method 'bad(List<String>)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L218
Parameter 'l' is not assigned and could be declared final
- 🟡 `pmd:UnusedLocalVariable` L219
Avoid unused local variables such as 'arr'.
- 🟡 `pmd:OptimizableToArrayCall` L219
This call to Collection.toArray() may be optimizable
- 🟡 `pmd:AtLeastOneConstructor` L224
Each class should declare at least one constructor
- 🟡 `pmd:RedundantFieldInitializer` L225
Avoid using redundant field initializer for 'x'
- 🟡 `pmd:CommentDefaultAccessModifier` L225
Missing commented default access modifier on field 'x'
- 🟡 `pmd:RedundantFieldInitializer` L226
Avoid using redundant field initializer for 'b'
- 🟡 `pmd:CommentDefaultAccessModifier` L226
Missing commented default access modifier on field 'b'
- 🟡 `pmd:AtLeastOneConstructor` L230
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L231
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L231
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:UnusedLocalVariable` L232
Avoid unused local variables such as 't'.
- 🟡 `pmd:AtLeastOneConstructor` L237
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L238
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L238
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:UnusedLocalVariable` L239
Avoid unused local variables such as 't'.
- 🟡 `pmd:StringToString` L239
Avoid calling toString() on String objects; this is unnecessary.
- 🟡 `pmd:AtLeastOneConstructor` L244
Each class should declare at least one constructor
- 🟡 `pmd:LooseCoupling` L245
Avoid using implementation types like 'Vector'; use the interface instead
- 🟡 `pmd:ReplaceVectorWithList` L245
Consider replacing this Vector with the newer java.util.List
- 🟡 `pmd:CommentDefaultAccessModifier` L245
Missing commented default access modifier on field 'v'
- 🟡 `pmd:ReplaceVectorWithList` L245
Consider replacing this Vector with the newer java.util.List
- 🟡 `pmd:UseArrayListInsteadOfVector` L245
Use ArrayList instead of Vector
- 🟡 `pmd:AtLeastOneConstructor` L249
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L250
Missing commented default access modifier on method 'bad(String[])'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L250
Parameter 'arr' is not assigned and could be declared final
- 🟡 `pmd:LocalVariableCouldBeFinal` L251
Local variable 'l' could be declared final
- 🟡 `pmd:LocalVariableCouldBeFinal` L252
Local variable 's' could be declared final
- 🟡 `pmd:UseArraysAsList` L253
Use asList instead of tight loops
- 🟡 `pmd:AtLeastOneConstructor` L259
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L260
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L260
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:UseIndexOfChar` L261
String.indexOf(char) is faster than String.indexOf(String).
- 🟡 `pmd:AtLeastOneConstructor` L266
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L267
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:UnusedAssignment` L268
The value assigned to variable 's' is never used
- 🟡 `pmd:AtLeastOneConstructor` L273
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L274
Missing commented default access modifier on method 'bad(StringBuffer)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L274
Parameter 'sb' is not assigned and could be declared final
- 🟡 `pmd:UseStringBufferLength` L275
This is an inefficient use of CharSequence.toString; call CharSequence.length instead.
- 🟡 `pmd:AtLeastOneConstructor` L280
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L281
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L281
Parameter 's' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L287
Each class should declare at least one constructor
- 🟡 `pmd:UnusedPrivateMethod` L288
Avoid unused private methods such as 'bad1()'.
- 🟡 `pmd:AvoidCalendarDateCreation` L289
A Calendar is used to get the current time, this is expensive.
- 🟡 `pmd:UnusedPrivateMethod` L291
Avoid unused private methods such as 'bad2()'.
- 🟡 `pmd:AvoidCalendarDateCreation` L292
A Calendar is used to get the current time, this is expensive.
- 🟡 `pmd:AtLeastOneConstructor` L297
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L298
Missing commented default access modifier on method 'bar(String)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L298
Parameter 'string' is not assigned and could be declared final
- 🟡 `pmd:InefficientEmptyStringCheck` L299
String.trim().length() == 0 / String.trim().isEmpty() is an inefficient way to validate a blank String.
- 🟡 `pmd:AtLeastOneConstructor` L306
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L307
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L308
Local variable 'sb' could be declared final
- 🟡 `pmd:InefficientStringBuffering` L308
Avoid concatenating nonliterals in a StringBuffer/StringBuilder constructor or append().
- 🟡 `pmd:AtLeastOneConstructor` L314
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L315
Missing commented default access modifier on method 'bad(String)'
- 🟡 `pmd:LocalVariableCouldBeFinal` L316
Local variable 'sb' could be declared final
- 🟡 `pmd:InsufficientStringBufferDeclaration` L316
StringBuilder has been initialized with size 16, but has at least 64 characters appended.
- 🟡 `pmd:AtLeastOneConstructor` L323
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L324
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UseStringBufferForStringAppends` L327
Prefer StringBuilder (non-synchronized) or StringBuffer (synchronized) over += for concatenating strings
- 🟡 `pmd:CommentDefaultAccessModifier` L331
Missing commented default access modifier on method 'getString(int)'
- 🟡 `pmd:MethodArgumentCouldBeFinal` L331
Parameter 'i' is not assigned and could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L337
Each class should declare at least one constructor
- 🟡 `pmd:PublicMemberInNonPublicType` L338
Public member 'convert' declared in a non-public type
- 🟡 `pmd:MethodArgumentCouldBeFinal` L338
Parameter 'i' is not assigned and could be declared final
- 🟡 `pmd:LocalVariableCouldBeFinal` L339
Local variable 's' could be declared final
- 🟡 `pmd:UselessStringValueOf` L340
No need to call String.valueOf to append to a string.
- 🟡 `pmd:AtLeastOneConstructor` L350
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L351
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L352
Local variable 'key' could be declared final
- 🟡 `pmd:HardCodedCryptoKey` L352
Do not use hard coded encryption keys
- 🟡 `pmd:RelianceOnDefaultCharset` L352
Specify a character set instead of relying on the default charset
- 🟡 `pmd:AtLeastOneConstructor` L358
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L359
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L360
Local variable 'iv' could be declared final
- 🟡 `pmd:AtLeastOneConstructor` L366
Each class should declare at least one constructor
- 🟡 `pmd:CommentDefaultAccessModifier` L367
Missing commented default access modifier on method 'bad()'
- 🟡 `pmd:UseShortArrayInitializer` L368
Array initialization can be written shorter
- 🟡 `pmd:LocalVariableCouldBeFinal` L368
Local variable 'iv' could be declared final
- 🟡 `pmd:InsecureCryptoIv` L368
Do not use hard coded initialization vector in crypto operations
- 🟡 `pmd:CommentDefaultAccessModifier` L371
Missing commented default access modifier on method 'alsoBad()'
- 🟡 `pmd:LocalVariableCouldBeFinal` L372
Local variable 'iv' could be declared final
- 🟡 `pmd:InsecureCryptoIv` L372
Do not use hard coded initialization vector in crypto operations
- 🟡 `pmd:RelianceOnDefaultCharset` L372
Specify a character set instead of relying on the default charset
- 🔵 `pmd:UnnecessaryImport` L12
Unused import 'java.util.Hashtable'
- 🔵 `pmd:UnnecessaryImport` L13
Unused import 'java.io.File'
- 🔵 `pmd:UnnecessaryImport` L15
Unused import 'java.io.FileOutputStream'
- 🔵 `pmd:UnnecessaryImport` L19
Unused import 'java.util.Arrays'
- 🔵 `pmd:DontCallThreadRun` L50
Dont call Thread.run() explicitly, use Thread.start()
- 🔵 `pmd:UnnecessaryFullyQualifiedName` L114
Unnecessary qualifier 'java.util': 'Date' is already in scope because it is imported in this file
- 🔵 `pmd:UseVarargs` L138
Consider using varargs for methods or constructors which take an array the last parameter.
- 🔵 `pmd:UseVarargs` L250
Consider using varargs for methods or constructors which take an array the last parameter.
@@ -0,0 +1,36 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\nopackage\NoPackageDemo.java`
**语言:** java
**耗时:** 52.0s
**分析工具:** pmd
---
总计: 6 | 错误: 1 | 警告: 3 | 建议: 2
静态分析 · 4 个问题
- 🔴 `pmd:SystemPrintln` L8
使用了 System.out/err 输出,应避免直接写控制台。
建议: 改用日志框架记录信息,例如:Logger.getGlobal().info("no package");(需要 import java.util.logging.Logger;或使用 SLF4J 等)。
- 🟡 `pmd:NoPackage` L6
所有类、接口、枚举和注解必须属于命名包(当前文件缺少 package 声明)。
建议: 在文件顶部添加 package 声明,例如:package com.example; 并确保目录结构与之匹配。
- 🟡 `pmd:AtLeastOneConstructor` L6
每个类应至少声明一个构造函数(当前类没有显式构造函数)。
建议: 为类添加一个无参构造函数:NoPackageClass() {},或在需要时提供带参构造函数。
- 🟡 `pmd:CommentDefaultAccessModifier` L7
方法 'm()' 缺少注释的默认(包私有)访问修饰符。
建议: 为默认访问级别的方法添加注释,例如:/* default */ void m() {;或显式改为 public/private 并添加相应注释。
AI 审查 · 2 条建议
- 🔵 [AI] [style] `missing-javadoc` L6
**类缺少 Javadoc 注释**
类 NoPackageClass 没有任何 Javadoc 注释,无法说明类的用途和意图,降低代码可维护性。
建议: 在类声明前添加 Javadoc 注释,例如:/** 示例类,用于演示 PMD 规则。 */
- 🔵 [AI] [design] `method-could-be-static` L7
**方法 m() 可以声明为 static**
方法 m() 不访问任何实例字段,也不使用 this,符合静态方法的特征。若声明为 static,可通过类名直接调用,语义更清晰。
建议: 将 void m() 改为 static void m()。
@@ -0,0 +1,40 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\BadCase\PackageCaseDemo.java`
**语言:** java
**耗时:** 109.8s
**分析工具:** pmd
---
总计: 7 | 错误: 1 | 警告: 5 | 建议: 1
静态分析 · 4 个问题
- 🔴 `pmd:SystemPrintln` L8
使用了 System.out/err 进行输出
建议: 不要直接使用 `System.out.println`,应改用日志框架(如 `java.util.logging.Logger` 或 SLF4J)输出。例如:`Logger.getLogger(PackageCaseDemo.class).info("bad package case");`,并添加相应导入和 Logger 字段。
- 🟡 `pmd:PackageCase` L4
包名包含大写字母
建议: 包名应全部小写,以符合 Java 命名规范。建议将 `BadCase` 改为 `badcase`,即 `package com.demo.badcase;`
- 🟡 `pmd:AtLeastOneConstructor` L6
每个类应至少声明一个构造器
建议: 为类 `PackageCaseDemo` 添加显式构造器。若类设计为不可实例化,应添加私有构造器;否则添加默认可见性的构造器。例如:`PackageCaseDemo() { }`
- 🟡 `pmd:CommentDefaultAccessModifier` L7
方法 'm()' 缺少默认访问修饰符的注释
建议: 该方法使用默认(包私有)访问权限,请添加注释说明,例如 `/* default */``// default`。建议:`/* default */ void m() {`
AI 审查 · 3 条建议
- 🟡 [AI] [design] `explicit-access-modifier` L6
**类和方法使用隐式包私有访问权限**
`PackageCaseDemo` 类和 `m()` 方法均未声明访问修饰符,使用包私有默认权限。这会降低可维护性,外部包无法访问,且意图不明确。若允许外部使用,应显式声明 `public`;若仅限包内使用,至少按 PMD 要求添加注释,但自定义访问修饰符更清晰。
建议: 根据设计意图显式添加修饰符。若计划作为公开 API,写为 `public class PackageCaseDemo { public void m() { ... } }`;若希望保持包私有,可保留现状但补充注释。
- 🟡 [AI] [design] `method-could-be-static` L7
**方法 m() 可以声明为 static**
方法 `m()` 没有访问任何实例字段或实例方法,因此不需要实例上下文。将其声明为 `static` 可以避免强制创建无状态实例,并明确表达该方法属于类级别。
建议: 将 `void m()` 改为 `static void m()`;如果只是打印固定文本,建议同时将方法重命名为描述性名称,如 `printBadPackageMessage`
- 🔵 [AI] [design] `missing-javadoc` L6
**类和方法缺少 Javadoc 文档注释**
`PackageCaseDemo` 类和 `m()` 方法没有 Javadoc 注释,无法说明类目的、方法和预期行为。虽然这是演示代码,但良好的公共 API 应提供文档注释。
建议: 为类添加 Javadoc`/** ... */`,为方法添加 `/** 输出包名错误提示 */`
@@ -0,0 +1,45 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\jsp\SecurityDemo.jsp`
**语言:** html
**耗时:** 56.5s
**分析工具:** jsp
---
总计: 8 | 错误: 3 | 警告: 5 | 建议: 0
AI 审查 · 8 条建议
- 🔴 [AI] [bug] `missing-jstl-taglib-declaration` L1
**缺少 JSTL 标签库声明**
页面在第 20 行使用了 JSTL core 标签 <c:out>,但未在页面顶部声明 taglib,导致 JSP 无法编译或运行时抛出标签解析异常。
建议: 在页面顶部添加 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 指令。
- 🔴 [AI] [security] `xss-unescaped-el-expression` L16
**未转义的 EL 表达式导致跨站脚本(XSS)**
第 16 行直接将用户可控的 ${userInput} 输出到 HTML 上下文,未进行任何编码,攻击者可通过构造恶意脚本实施反射型 XSS 攻击。
建议: 使用 <c:out> 或 fn:escapeXml() 对输出进行 HTML 实体转义,例如 <c:out value="${userInput}"/>。
- 🔴 [AI] [security] `xss-unescaped-el-expression` L17
**未转义的 EL 表达式导致跨站脚本(XSS)**
第 17 行直接将用户可控的 ${searchTerm} 输出到 HTML 上下文,未进行任何编码,攻击者可通过构造恶意脚本实施反射型 XSS 攻击。
建议: 使用 <c:out> 或 fn:escapeXml() 对输出进行 HTML 实体转义,例如 <c:out value="${searchTerm}"/>。
- 🟡 [AI] [style] `missing-page-encoding-directive` L1
**JSP 页面缺少 pageEncoding 指令**
虽然 contentType 中指定了 charset,但 JSP 源文件的编码最好通过 pageEncoding 明确指定,避免不同容器对源文件编码的误判。
建议: 在 page 指令中添加 pageEncoding="UTF-8" 属性。
- 🟡 [AI] [style] `missing-doctype-declaration` L6
**缺少 HTML 文档类型声明**
页面未声明 <!DOCTYPE html>,可能导致浏览器以 Quirks 模式渲染,造成样式和布局不一致。
建议: 在 <html> 标签前添加 <!DOCTYPE html>。
- 🟡 [AI] [security] `iframe-missing-src-attribute` L12
**iframe 缺少 src 属性**
第 12 行的 iframe 没有 src 属性,会渲染为空白区域,且可能被用作恶意行为(如点击劫持)的容器;若用作占位,建议给出明确的来源或移除。
建议: 为 iframe 添加有效的 src 属性,或使用其他 HTML 元素代替空 iframe。
- 🟡 [AI] [security] `iframe-missing-src-attribute` L13
**iframe 缺少 src 属性**
第 13 行的 iframe 没有 src 属性,会渲染为空白区域,且可能被用作恶意行为(如点击劫持)的容器;若用作占位,建议给出明确的来源或移除。
建议: 为 iframe 添加有效的 src 属性,或使用其他 HTML 元素代替空 iframe。
- 🟡 [AI] [security] `iframe-missing-sandbox-attribute` L21
**iframe 缺少 sandbox 属性**
当 iframe 加载外部内容时,未设置 sandbox 属性,会让嵌入式内容拥有与页面相同的权限,存在点击劫持、脚本执行等风险。建议为 iframe 添加 sandbox 属性,并按需开启权限。
建议: 为 iframe 添加 sandbox="allow-scripts allow-same-origin" 等最小化权限,或使用空 sandbox 属性以获取最高隔离级别。
@@ -0,0 +1,55 @@
# 代码审查报告
**文件:** `data\demo-pmd\src\com\demo\errorprone\extra\StaticEJBFieldDemo.java`
**语言:** java
**耗时:** 137.9s
**分析工具:** pmd
---
总计: 12 | 错误: 4 | 警告: 6 | 建议: 2
静态分析 · 9 个问题
- 🔴 `pmd:FieldNamingConventions` L11
静态字段名 'CountA' 不符合命名约定 '[a-z][a-zA-Z0-9]*'
建议: 将 CountA 重命名为以小写字母开头,例如 `countA`;同时更新 work() 中对 CountA 的引用。
- 🔴 `pmd:FieldNamingConventions` L12
字段名 'CountC' 不符合命名约定 '[a-z][a-zA-Z0-9]*'
建议: 将 CountC 重命名为 `countC`
- 🔴 `pmd:SystemPrintln` L20
使用了 System.out/err
建议: 避免在代码中使用 System.out/err,建议使用日志框架。例如 `java.util.logging.Logger.getLogger(...).info(...)`
- 🟡 `pmd:AtLeastOneConstructor` L10
每个类应至少声明一个构造函数
建议: 为 SomeEJB 添加一个显式 public 无参构造函数,例如 `public SomeEJB() { }`。这对 EJB 容器实例化类是必要的。
- 🟡 `pmd:UnusedPrivateField` L11
避免未使用的私有字段,例如 'CountA'
建议: CountA 在 work() 中只被自增(写入)而从未被读取,属于无实际业务意义的字段。建议删除该字段以及自增语句;如果确实需要计数器,请改为实例字段并提供 getter 或使用 AtomicInteger。
- 🟡 `pmd:StaticEJBFieldShouldBeFinal` L11
EJB 不应拥有非 final 的静态字段
建议: 将 CountA 改为实例变量(去掉 static),避免被 EJB 池中所有实例共享;如果该值应保持不变,请声明为 `private final` 常量,但当前代码对它自增,所以应改为实例变量。
- 🟡 `pmd:CommentDefaultAccessModifier` L12
字段 'CountC' 缺少默认访问修饰符的注释
建议: 请在 CountC 前添加 `/* default */` 注释来显式说明包私有访问权限,或改为显式修饰符,如 `private`/`protected`/`public`
- 🔵 `pmd:RemoteInterfaceNamingConvention` L10
会话 EJB 的远程接口不应带有 EJB 后缀
建议: 如果 SomeEJB 是远程接口,应重命名为 `Some``SomeRemote`,去掉 `EJB` 后缀;如果是 EJB 实现类,应重新设计类的职责,避免与远程接口混淆。
- 🔵 `pmd:LocalHomeNamingConvention` L10
会话 EJB 的本地 Home 接口应以 LocalHome 为后缀
建议: 当前类被 PMD 视为本地 Home 接口,名称应改为 `SomeLocalHome` 或以 `LocalHome` 结尾。注意 Home 接口应为接口类型,不应作为类实现。
AI 审查 · 3 条建议
- 🔴 [AI] [bug] `invalid-ejb-type-hierarchy` L10
**EJB 类继承/实现关系错误,导致编译失败**
SomeEJB 使用 `extends EJBObject`,但 `EJBObject` 是接口,类不能 extend 接口;同时 `implements EJBLocalHome` 需要实现该接口中的 `remove` 等方法,而 SomeEJB 并未实现。此类代码无法通过编译。请重新设计 EJB 类与接口关系。
建议: 如果 SomeEJB 是 EJB 实现类,应改为 `public class SomeEJB implements javax.ejb.SessionBean { ... }` 并实现 ejbActivate/ejbPassivate/ejbRemove/setSessionContext 等方法;如果要定义远程接口,应使用 `public interface SomeEJB extends EJBObject`,且去掉 EJB 后缀;本地 Home 接口应使用 `public interface SomeLocalHome extends EJBLocalHome`
- 🟡 [AI] [design] `unused-package-private-field` L12
**CountC 未使用且包私有,增加无谓的可见性**
CountC 没有被任何代码读取或写入,且包私有(默认访问权限),会破坏封装,并让同包其他类能意外访问可变状态。
建议: 删除该字段;如果确实需要该数据,请改为 `private int countC;` 并通过 getter/setter 访问。
- 🟡 [AI] [bug] `non-atomic-increment` L14
**CountA++ 非原子操作,存在并发更新丢失风险**
CountA 是静态字段,在 EJB 容器的多线程环境中会被多个线程共享。`CountA++` 是读-改-写复合操作,多个线程同时执行时可能互相覆盖,导致计数不准确。同时私有字段没有读取入口,计数结果对外也不可见。
建议: 若需要计数器,请改为实例字段(如 `private int countA;`),或使用 `java.util.concurrent.atomic.AtomicInteger` 并声明为 `private final`。若使用 AtomicInteger,则在 work() 中调用 `countA.incrementAndGet()`,并提供 getter 读取值。