Подтвердить что ты не робот

Как обрабатывать Findbugs "Непрерывное несериализуемое поле экземпляра в сериализованном классе"?

Рассмотрим следующий класс. Если я запустил Findbugs против него, это даст мне ошибку ( "Непрерывное несериализуемое поле экземпляра в сериализуемом классе" ) в строке 5, но не в строке 7.

1 public class TestClass implements Serializable {
2
3  private static final long serialVersionUID = 1905162041950251407L;
4
5  private Set<Integer> mySet;      // Findbugs error
6
7  private HashSet<Integer> myOtherSet;
8
9 }

Это правильно, потому что java.util.Set никогда не реализует Serializable в своей иерархии и java.util.HashSet. Однако лучше всего использовать код вместо интерфейсов вместо конкретных реализаций.

Как я могу лучше всего справиться с этим?

Я могу добавить @Suppresswarnings (justification = "No bug", values ​​= "SE_BAD_FIELD" ) в строке 3. У меня довольно много наборов и списков в моем фактическом коде, и я боюсь, что это пометит мой код слишком много.

Есть ли лучшие способы?

4b9b3361

Ответ 1

Однако лучше всего использовать код вместо интерфейсов вместо бетона реализации.

Я утверждаю, что нет, в этом случае это не так. Findbugs совершенно правильно сообщает вам, что вы рискуете запуском в NotSerializableException, как только в этом поле будет реализована несериализуемая реализация Set. Это то, с чем вам нужно иметь дело. Как, это зависит от дизайна ваших классов.

  • Если эти коллекции инициализируются внутри класса и никогда не устанавливаются извне, я абсолютно ничего не вижу в объявлении конкретного типа для поля, так как поля все равно являются деталями реализации. Используйте тип интерфейса в общедоступном интерфейсе.
  • Если коллекция передается в класс через открытый интерфейс, вы должны убедиться, что они фактически Serializable. Для этого создайте интерфейс SerializableSet extends Set, Serializable и используйте его для своего поля. Затем либо:
    • Используйте SerializableSet в общедоступном интерфейсе и предоставляйте классы реализации, которые его реализуют.
    • Проверять коллекции, переданные классу через instanceof Serializable, а если нет, скопируйте их в нечто, что есть.

Ответ 2

Я знаю, что это уже старый вопрос, который уже ответил, но только потому, что другие знают, что вы можете установить поле Set<Integer> как переходное, если у вас нет интереса к сериализации этого конкретного поля, которое исправит вашу ошибку FindBugs.

public class TestClass implements Serializable {

    private static final long serialVersionUID = 1905162041950251407L;
    private transient Set<Integer> mySet;

}

Я предпочитаю этот метод вместо того, чтобы принуждать пользователей вашего API к вашему конкретному типу, если только он не является внутренним, тогда ответ Майкла Боргвардта имеет смысл.

Ответ 3

Вы можете использовать помощник захвата, чтобы убедиться, что переданный в Set поддерживает два интерфейса:

private static class SerializableTestClass<T extends Set<?> & 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 <T extends Set<?> & Serializable> Serializable forSerializableSet(T set)
    {
        return new SerializableTestClass<T>(set);
    }
}

Таким образом, вы можете иметь общедоступный API, который принудительно выполняет Serializable, не проверяя/не требуя конкретных деталей реализации.

Ответ 4

Я использую фильтр findbugs-exclude для коллекции-полей:

<Match>
    <Field type="java.util.Map" />
    <Bug pattern="SE_BAD_FIELD" />
</Match>
<Match>
    <Field type="java.util.Set" />
    <Bug pattern="SE_BAD_FIELD" />
</Match>
<Match>
    <Field type="java.util.List" />
    <Bug pattern="SE_BAD_FIELD" />
</Match>

См. http://findbugs.sourceforge.net/manual/filter.html

Ответ 5

Вы можете избавиться от этих предупреждающих сообщений Critical, добавив в свой класс следующие методы:

private void writeObject(ObjectOutputStream stream)
        throws IOException {
    stream.defaultWriteObject();
}

private void readObject(ObjectInputStream stream)
        throws IOException, ClassNotFoundException {
    stream.defaultReadObject();
}

Ответ 6

Используйте конкретный набор Serializable для вашего внутреннего представления, но при использовании любых открытых интерфейсов используйте интерфейс Set.

public class TestClass implements Serializable {
    private static final long serialVersionUID = 1905162041950251407L;

    private HashSet<Integer> mySet;

    public TestClass(Set<Integer> s) {
        super();
        setMySet(s);
    }

    public void setMySet(Set<Integer> s) {
        mySet = (s == null) ? new HashSet<>() : new HashSet<>(s);
    }
}

Ответ 7

использовать

private transient Set<Integer> mySet;

Ответ 8

Если вы используете findbugs-maven-plugin и должны сохранять поле, и это поле является классом, не реализующим интерфейс Serializable, например, поле, которое имеет класс, определенный третьим лицом. Вы можете вручную настроить файл исключения для findbugs,

Если это единственный случай, добавьте его в файл exclude: П:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>findbugs-maven-plugin</artifactId>
    <version>3.0.3</version>
    <configuration>
          <xmlOutput>true</xmlOutput>
          <xmlOutputDirectory>target/findbugs/</xmlOutputDirectory>
          <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>
          <includeFilterFile>findbugs-include.xml</includeFilterFile>
          <failOnError>true</failOnError>
    </configuration>
...

exclude.xml:

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
    <Match>
        <Class name="com.xxx.Foo" /> 
        <Field type="org.springframework.statemachine.StateMachineContext"/>
    </Match>

Entity:

@Entity
public class Foo extends Boo {
    StateMachineContext<A, B> stateMachineContext;

Хотя я не понимаю, почему добавление <Bug category="SE_BAD_FIELD"/> не работает. Кроме того, я не согласен с решением добавления аннотации в поле типа @edu.umd.cs.findbugs.annotations.SuppressWarnings(justification="No bug", values="SE_BAD_FIELD"), потому что строительные инструменты лучше не проникают в бизнес-код. использование плагина maven и фильтры findbugs включают и исключают

О SE_BAD_FIELD: Непрерывное несериализуемое поле экземпляра в сериализованном классе, я думаю, что он не должен проверять сущности. Поскольку javax.persistence.AttributeConverter предлагает методы для сериализации внешней стороны поля (реализует Serializable - это внутренний метод для сериализации).