Понимание этого предупреждения: сериализуемый класс не объявляет статический финал serialVersionUID

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

Это верно, что модульные тесты движущегося API являются хрупкими, но поблочное тестирование является также эффективным на проектах API меньше, таких как приложения. Поблочное тестирование предназначено для тестирования единиц, с которыми сделан проект. Это позволяет гарантировать каждой единице работы как ожидалось. Это - реальная система поддержки при изменении - осуществляющий рефакторинг - код.

Насколько размер проекта затронут, Это верно, что запись модульных тестов на маленький проект может быть излишеством. И здесь, я определил бы маленький проект как небольшую программу, которая может быть протестирована вручную, но очень легко и быстро, через не больше, чем несколько секунд. Также маленький проект может вырасти, в этом случае могло бы быть выгодно иметь модульные тесты под рукой.

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

Безотносительно процесса разработки, поблочное тестирование не предназначено, чтобы заменить любые другие этапы теста, но дополнить их тестами на уровне разработки, так, чтобы разработчики могли получить очень раннюю обратную связь, не имея необходимость ожидать официальной сборки и официального теста. С поблочным тестированием группа разработчиков поставляет код, который работает, в нисходящем направлении, не код без ошибки, но кодируйте, который может быть протестирован тестовой командой (командами).

Таким образом, я тестирую вручную, когда действительно очень легко, или когда запись модульных тестов будет слишком сложна, и я не нацеливаюсь к 100%-му покрытию.

21
задан Alex Baranosky 26 January 2010 в 04:56
поделиться

6 ответов

Синтаксис, который вы используете, называется инициализация двойных скобок , который на самом деле является блоком инициализации экземпляра , который является частью анонимного внутреннего класса "(конечно, не взлом). Итак, используя эту нотацию, вы фактически определяете новый класс (!).

«Проблема» в вашем случае заключается в том, что HashMap реализует Serializable . Этот интерфейс не имеет никаких методов, и служит только для определения семантики сериализуемости . Другими словами, это интерфейс маркера, и вам конкретно не нужно ничего реализовывать. Но во время десериализации Java использует номер версии, называемый serialVersionUID , чтобы убедиться, что сериализованная версия совместима с целью. Если вы не предоставите этот serialVersionUID , он будет рассчитан. И, как описано в документации javadoc Serializable , вычисленное значение чрезвычайно чувствительно, и поэтому рекомендуется явно объявить его, чтобы избежать проблем с десериализацией. И это то, на что Eclipse «жалуется» (обратите внимание, что это всего лишь предупреждение).

Итак, чтобы избежать этого предупреждения, вы можете добавить serialVersionUID к вашему анонимному внутреннему классу:

someMethodThatTakesAHashMap(new HashMap<String, String>() {
    private static final long serialVersionUID = -1113582265865921787L;

    {
        put("a", "value-a");
        put("c", "value-c");
    }
});

Но вы теряете лаконичность синтаксиса (и, возможно, он вам даже не понадобится).

Другой вариант - игнорировать предупреждение, добавив @SuppressWarnings ("серийный номер") к методу, в котором вы вызываете someMethodThatTakesAHashMap (Map) . Это кажется более подходящим в вашем случае.

Все это сказано, хотя этот синтаксис лаконичен, он имеет некоторые недостатки. Во-первых, если вы держите ссылку на объект, инициализированный с помощью инициализации с двойными скобками, вы неявно удерживаете ссылку на внешний объект, который не будет иметь права на сборку мусора. Так что будь осторожен. Во-вторых (хотя это звучит как микрооптимизация), инициализация двойных скобок имеет очень небольшие накладные расходы . В-третьих, этот метод фактически использует анонимные внутренние классы, как мы видели, и, таким образом, съедает немного перманентного пространства (но я сомневаюсь, что это действительно проблема, если вы действительно не злоупотребляете ими). Наконец - и это, возможно, самый важный момент - я не уверен, что это делает код более читабельным (это не очень известный синтаксис).

Итак, хотя мне нравится использовать его в тестах (для краткости), я стараюсь избегать использования его в «обычном» коде.

28
ответ дан 29 November 2019 в 21:07
поделиться

Да, вы можете подавить предупреждение, но я бы переписал его так:

HashMap<String, String> map  = new HashMap<String, String>();
map.put("a","value-a"); 
map.put("c","value-c");
someMethodThatTakesAHashMap(map);

Подавление не требуется, и его гораздо лучше читать, IMO.

6
ответ дан 29 November 2019 в 21:07
поделиться

Ваше намерение было инициализировать анонимный экземпляр hashmap. Предупреждение - это подсказка, что ваш код делает больше, чем вы предназначены.

То, что мы ищем, это способ инициализации анонимного экземпляра Hashmap. Выше у нас выше, создает анонимный подкласс hashmap, затем создает анонимный экземпляр этого анонимного класса.

Потому что код делает больше, чем было предназначено, я бы назвал это взлом.

Что мы действительно хочем, это что-то вроде этого:

foo(new HashMap<String, String>({"a", "value-a"}, {"c", "value-c"}));

, но увы это не действительна Java. Там нет способа сделать все это в безопасном виде, используя массив пар клавиш / значений. Java Simple не имеет выразительной силы.

ImmutableMap Google ImmutableMap. Статические методы близки, но это означает создание версии фабричного метода для различных чисел пар / значение пар. (См. Ответ Finnw.)

Так что держите вещи простыми. Перейдите с решением BART K, если ваш код не будет изменяться этой инициализацией. Если это так, используйте ImmutableMap. Или сверните свой собственный подкласс HASHMAP с «« из »стилей заводских методов. Или создайте эти "« Стиль заводских методов в утилите. Вот один для двух пар ключевых / значений:

public final MapUtil {
    public static <K,V> Map<K,V> makeMap(K k1, V v1, K k2, V v2) {
        Map<K,V> m = new HashMap<K,V>();
        m.put(k1, v1);
        m.put(k2, v2);
        return m;
    }
}

Охватывают извлеченность и примите утешение в знаниях, которые ваши корпоративные сотрудники носят одни и те же кандалы, как и вы.

0
ответ дан 29 November 2019 в 21:07
поделиться

Чтобы решить другую половину вашего вопроса: «Должен ли я подавить это?» -

Да. На мой взгляд, это ужасное предупреждение. SERIALVERSUID должен по умолчанию не используется, а не наоборот.

Если вы не добавляете SerialVersionUID, худшее, что происходит, состоит в том, что две версии объекта, которые на самом деле совместимы с сериализацией, считаются несовместимыми. SerialVersionuit - это способ заявить, что совместимость сериализации не изменилась, переопределяя оценку Java по умолчанию.

Использование SerialVersionUID, худшее, что происходит, является то, что вы непреднамеренно не можете обновить идентификатор, когда сериализованная форма класса изменяется несовместимым способом. В лучшем случае вы также получаете ошибку выполнения. В худшее, что-то хуже случается. И представьте, насколько легко не удалось обновить его.

0
ответ дан 29 November 2019 в 21:07
поделиться

Я обычно согласен с BART K., но для информационных целей:
Предупреждение также может быть устранено путем добавления поля, которое может быть автоматически сгенерировано путем удара Ctrl + 1.
Предупреждение также может быть подавлено путем добавления аннотации @suppresswarning («серийный») до определения.
Анонимный класс реализует сериализацию, и сериализуемое требует этого статического поля, чтобы версии можно отличить, когда сериализация и десериализация. Больше информации здесь:
http://www.javablogging.com/what-is-serialversionud/

0
ответ дан 29 November 2019 в 21:07
поделиться

ImmutableMap Класс класс из библиотеки коллекции Google полезен для этой ситуации. например

someMethodThatTakesAHashMap(ImmutableMap.<K, V>builder().put("a","value-a").put("c","value-c").build());

ИЛИ

someMethodThatTakesAHashMap(ImmutableMap.of("a","value-a","c","value-c"));
0
ответ дан 29 November 2019 в 21:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: