274 lines
17 KiB
Markdown
274 lines
17 KiB
Markdown
# 代码审查报告
|
||
|
||
**文件:** `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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L16
|
||
L16: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L22
|
||
L22: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L28
|
||
L28: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L34
|
||
L34: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L34
|
||
L34: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L46
|
||
L46: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L46
|
||
L46: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L52
|
||
L52: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:AvoidLiteralsInIfCondition` L56
|
||
L56: 避免在 if 语句中使用字面量(如 10)
|
||
建议: 定义常量并替换:private static final int THRESHOLD_10 = 10; 条件改为 x > THRESHOLD_10。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L61
|
||
L61: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L61
|
||
L61: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L69
|
||
L69: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L82
|
||
L82: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L82
|
||
L82: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L88
|
||
L88: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L97
|
||
L97: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L97
|
||
L97: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L103
|
||
L103: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:TooFewBranchesForSwitch` L106
|
||
L106: 分支少于三个的 switch 效率较低,建议改用 if 语句
|
||
建议: 将 switch (i % 2) 改为 if-else:if (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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L114
|
||
L114: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L120
|
||
L120: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L126
|
||
L126: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L132
|
||
L132: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L140
|
||
L140: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L146
|
||
L146: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L152
|
||
L152: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L152
|
||
L152: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final int x。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L168
|
||
L168: 参数 'd' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final ExternalData d。
|
||
- 🟡 `pmd:MethodArgumentCouldBeFinal` L168
|
||
L168: 参数 'x' 未被赋值,可声明为 final
|
||
建议: 将参数声明为 final:final 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
|
||
**条件表达式恒为真**
|
||
rule3(L31)与 rule18(L149)中的 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 来自用户输入,可能形成拒绝服务攻击。
|
||
建议: 评估业务逻辑,避免将未受控的外部输入直接作为循环上限;考虑降低时间复杂度或增加上限校验。
|