Java PMD警告:非瞬态类成员

36

在这一行:

private boolean someFlag;

我收到以下PMD警告:

发现了非瞬态,非静态成员,请将其标记为瞬态或提供访问器。

请问有人能解释一下这个警告出现的原因和含义吗?(我知道如何修复它,但不知道为什么会出现...)

我在许多其他成员声明中也遇到了相同的问题...


编辑: 我的类绝对不是bean,也不是可序列化的...


不可序列化?你检查了继承层次结构吗? - tcurdt
100%不可序列化... - Yuval Adam
3
很多PMD检查是代码规范。如果它们不符合你的代码规范,我建议将它们关闭。 - Peter Lawrey
5个回答

9
我假设您的类是一个bean,根据定义实现了Serializable。transient变量将被排除在序列化过程之外。如果您对bean进行序列化然后再进行反序列化,该值实际上将具有默认值。
PMD假定您在处理可序列化的bean。对于一个bean,期望有所有成员变量的getter/setter。由于您省略了这些内容,暗示着您的成员变量不是bean的一部分......因此不需要进行序列化。如果是这种情况,您应该将其从序列化中排除。通过将变量标记为“transient”来实现。

18
我明白了,但这个类不是一个bean(Java中的一种对象)... PMD在我的背后做出了不相关的假设 :) - Yuval Adam

8
现在我明白了。
添加了这个定义后:
private boolean someFlag;

...很明显这里发生了什么:

这个错误信息确实涉及访问模式。PMD指出,被bean引用的类必须遵循bean模式。

最有可能支持属性样式访问,例如MyBean.referredClass.someFlag将被转换为someObject.getReferredClass().getSomeFlag()

PMD期望存在一个isSomeFlag/getSomeFlagsetSomeFlag方法,通过这些方法可以访问其值,而不是直接访问它。

Found non-transient, non-static member. Please mark as transient **or provide accessors**.

6

查看正在发生的规则此处

BeanMembersShouldSerialize

如果一个类是bean,或者直接或间接地被bean引用,则需要将其序列化。成员变量需要标记为瞬态、静态或在类中具有访问器方法。将变量标记为瞬态是最安全、最简单的修改方式。访问器方法应遵循Java命名约定,即如果您有一个名为foo的变量,则应提供getFoo和setFoo方法。


正如楼主所说,他的类不是一个bean。我也有同样的情况,即Sonar抱怨的不可序列化的非bean类。 - Florian F

2

transient被用作提示JVM序列化时,在写入流/磁盘时应该忽略它。因此,如果您的实例被恢复并成为内存中的对象,则该字段将为空。

静态成员的问题在于,在内存中只有一个静态成员。因此,在反序列化时不清楚应该发生什么。旧值是否应该保留?还是缓存版本覆盖旧值?

您应该做的是:根本不要在可序列化类中使用静态字段。将其移动到其他地方,或者更好的方法是根本不使用静态成员/单例。它们引入了全局状态,可能会导致许多问题和不良的OO设计。


但在初始示例中,someFlag不是静态的。 - Florian F

0

你可以用以下两种方式解决这个问题:

  1. 为成员变量添加getter和setter方法。
  2. 在构造函数中使用final关键字来设置成员变量的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接