56 lines
4.3 KiB
Markdown
56 lines
4.3 KiB
Markdown
# 代码审查报告
|
|
|
|
**文件:** `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 读取值。
|