非瞬态类成员的 Java PMD 警告
Posted
技术标签:
【中文标题】非瞬态类成员的 Java PMD 警告【英文标题】:Java PMD warning on non-transient class member 【发布时间】:2010-10-10 01:04:28 【问题描述】:在线:
private boolean someFlag;
我收到以下 PMD 警告:
找到非瞬态、非静态成员。请标记为瞬态或提供访问器。
有人可以解释为什么会出现此警告及其含义吗? (我知道如何解决它,但我不明白它为什么会在那里......)
我在许多其他成员声明中也得到了这一点......
编辑:我的课程绝对不是 bean,也不能序列化...
【问题讨论】:
不可序列化?你检查过继承层次吗? 100% 不可序列化... 很多 PMD 检查都是代码约定。如果它们不符合您的代码约定,我建议将它们关闭。 【参考方案1】:我假设您的类是根据定义实现 Serializable
的 bean。瞬态变量将从序列化过程中排除。如果您对 bean 进行序列化然后反序列化,则该值实际上将具有默认值。
PMD 假设您在这里处理的是可序列化的 bean。对于一个 bean,它应该有所有成员变量的 getter/setter。由于您省略了这些,因此您暗示您的成员变量不是 bean 的一部分 ....因此不需要序列化。如果是这种情况,您应该将其从序列化中排除。您可以通过将变量标记为“瞬态”来执行此操作。
【讨论】:
好的,我明白了,但课程不是 bean...PMD 在我背后做出不相关的假设 :)【参考方案2】:现在我明白了。
添加此定义后:
private boolean someFlag;
...这里发生了什么很清楚:
此错误消息确实涉及访问架构。 PMD 声明 bean 引用的类也必须遵循 bean 模式。
最有可能支持像MyBean.referredClass.someFlag
这样的属性样式访问将被转换为someObject.getReferredClass().getSomeFlag()
PMD 它期望有一个 isSomeFlag/getSomeFlag
和 setSomeFlag
方法,您可以通过它访问它的值,而不是直接访问它。
Found non-transient, non-static member. Please mark as transient **or provide accessors**.
【讨论】:
【参考方案3】:查看正在发生的规则here
BeanMembersShouldSerialize
如果一个类是一个 bean,或者被一个 bean 直接或间接引用,它需要是可序列化的。成员变量需要在类中标记为瞬态、静态或具有访问器方法。将变量标记为瞬态是最安全和最简单的修改。访问器方法应该遵循 Java 命名约定,即如果你有一个变量 foo,你应该提供 getFoo 和 setFoo 方法。
【讨论】:
正如 OP 所说,他的课程不是 bean。我也有 Sonar 抱怨的 not-a-bean no-serializable 类的情况。【参考方案4】:transient 用作 jvm 序列化的提示,当将类写入流/到磁盘时它应该忽略它。因此,如果您的实例被恢复并成为内存中的对象,则该字段将为空。
静态成员的问题是,内存中一次只有一个。所以它并不完全清楚反序列化时应该发生什么。应该保留旧值吗?还是缓存版本覆盖旧版本?
你应该做什么:不要在 Serializable 类中使用静态字段。将它移到其他地方,或者更好的是,根本不要使用静态成员/单例。它们引入了一个全局状态,这可能会导致许多问题和糟糕的 OO 设计。
【讨论】:
但 someFlag 在初始示例中不是静态的。【参考方案5】:您可以通过两种方式解决此问题:
-
为成员添加 getter 和 setter 方法。
使用构造函数添加 final 以设置成员的值。
【讨论】:
以上是关于非瞬态类成员的 Java PMD 警告的主要内容,如果未能解决你的问题,请参考以下文章
如何处理 Findbugs“可序列化类中的非瞬态不可序列化实例字段”?