java 类不能序列化_java-如何处理Findbugs“可序列化类中的非瞬态不可序列化实例字段”?...

java-如何处理Findbugs“可序列化类中的非瞬态不可序列化实例字段”?

考虑下面的类。 如果我对它运行Findbugs,它将在第5行而不是在第7行给我一个错误(“可序列化类中的非瞬态不可序列化实例字段”)。

1 public class TestClass implements Serializable {

2

3 private static final long serialVersionUID = 1905162041950251407L;

4

5 private Set mySet; // Findbugs error

6

7 private HashSet myOtherSet;

8

9 }

这是正确的,因为java.util.Set从未在其层次结构中实现Serializable,而java.util.HashSet却没有实现。但是,最佳实践是针对接口而不是具体的实现进行编码。

我该如何最好地处理呢?

我可以在第3行上添加@Suppresswarnings(justification =“ No bug”,values =“ SE_BAD_FIELD”)。我的实际代码中有很多Sets和Lists,恐怕它会使我的代码乱七八糟。

有更好的方法吗?

7个解决方案

28 votes

但是,最好的做法是进行编码   针对界面而非具体   实现。

我认为不可以,在这种情况下不是。 Findbugs非常正确地告诉您,一旦您在该字段中具有不可序列化的SerializableSet extends Set, Serializable实现,便有可能会遇到instanceof Serializable的风险。 这是您应该处理的事情。 如何,这取决于您的班级设计。

如果这些集合是在类中初始化的,并且从不从外部进行设置,那么声明字段的具体类型绝对不会出错,因为字段无论如何都是实现细节。 不要在公共接口中使用接口类型。

如果将集合通过公共接口传递给类,则必须确保它们实际上是instanceof Serializable。为此,请创建一个接口SerializableSet extends Set, Serializable,并将其用于您的字段。 然后,要么:在公共接口中使用instanceof Serializable,并提供实现它的实现类。

检查通过instanceof Serializable传递给班级的集合,如果不是,则将其复制到实际的集合中。

Michael Borgwardt answered 2020-01-05T16:50:49Z

12 votes

我知道这是一个已经解决的老问题,但是其他人也知道,如果您不希望序列化特定字段来解决FindBugs错误,可以将2689477726226026088960字段设置为瞬态。

public class TestClass implements Serializable {

private static final long serialVersionUID = 1905162041950251407L;

private transient Set mySet;

}

我更喜欢这种方法,而不是强迫API用户将其转换为您的具体类型,除非它只是内部类型,否则Michael Borgwardt的回答更有意义。

Graham answered 2020-01-05T16:51:14Z

9 votes

您可以通过在类中添加以下方法来摆脱那些Critical警告消息:

private void writeObject(ObjectOutputStream stream)

throws IOException {

stream.defaultWriteObject();

}

private void readObject(ObjectInputStream stream)

throws IOException, ClassNotFoundException {

stream.defaultReadObject();

}

Vlad Mihalcea answered 2020-01-05T16:51:39Z

8 votes

您可以使用捕获助手来确保传入的Set支持两个接口:

private static class SerializableTestClass & Serializable> implements Serializable

{

private static final long serialVersionUID = 1L;

private final T serializableSet;

private SerializableTestClass(T serializableSet)

{

this.serializableSet = serializableSet;

}

}

public static class PublicApiTestClass

{

public static & Serializable> Serializable forSerializableSet(T set)

{

return new SerializableTestClass(set);

}

}

这样,您可以拥有一个公共API,该API强制执行Serializable,而无需检查/要求特定的实现细节。

jontejj answered 2020-01-05T16:52:03Z

7 votes

我对集合字段使用findbugs-exclude过滤器:

参见[http://findbugs.sourceforge.net/manual/filter.html]

brabenetz answered 2020-01-05T16:52:28Z

1 votes

对内部表示使用具体的Serializable集,但使所有公共接口都使用Set接口。

public class TestClass implements Serializable {

private static final long serialVersionUID = 1905162041950251407L;

private HashSet mySet;

public TestClass(Set s) {

super();

setMySet(s);

}

public void setMySet(Set s) {

mySet = (s == null) ? new HashSet<>() : new HashSet<>(s);

}

}

Paul Croarkin answered 2020-01-05T16:52:48Z

-1 votes

如果您使用的是findbugs-maven-plugin且必须保留一个字段,并且该字段是未实现Serializable接口的类,例如,某个字段在第三方定义了一个类。 您可以手动为findbug配置排除文件,

如果只有这种情况,请将其添加到排除文件中:pom:

org.codehaus.mojo

findbugs-maven-plugin

3.0.3

true

target/findbugs/

findbugs-exclude.xml

findbugs-include.xml

true

...

exclude.xml:

实体:

@Entity

public class Foo extends Boo {

StateMachineContext stateMachineContext;

尽管我不明白为什么无法添加javax.persistence.AttributeConverter。 此外,我不同意在像@edu.umd.cs.findbugs.annotations.SuppressWarnings(justification="No bug", values="SE_BAD_FIELD")这样的字段上添加注释的解决方案,因为构建工具最好不要渗透业务代码.maven插件用法和findbugs过滤器都包括和排除

关于SE_BAD_FIELD:可序列化类中的非瞬态不可序列化实例字段,我认为不应检查实体。 因为javax.persistence.AttributeConverter提供了将字段外序列化的方法(实现Serializable是内部进行序列化的方法)。

Tiina answered 2020-01-05T16:53:31Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值