Главная страница
Навигация по странице:

  • Serialization API

  • ObjectInputStream

  • Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока


    Скачать 1.93 Mb.
    НазваниеJava io. Ключевым понятием здесь является понятие потока
    Дата03.07.2022
    Размер1.93 Mb.
    Формат файлаdoc
    Имя файлаОтветы на вопросы по ревью 4.doc
    ТипДокументы
    #623608
    страница25 из 39
    1   ...   21   22   23   24   25   26   27   28   ...   39

    Переопределение сериализации в интерфейсе Serializable


    Если у сериализуемого объекта реализован один из следующих методов, то механизм сериализации будет использовать его, а не метод по умолчанию :

    Ниже приводятся примеры использования данных методов.

    Сериализация не безопасна


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

    К счастью разработчиков Java Serialization API позволяет "вклиниться" в процесс сериализации, и изменить (или запутать) поля данных как перед сериализацией, так и после десериализации. Это можно сделать, определив методы writeObjectreadObject объекта Serializable.

    Изменение сериализованных данных, writeObject, readObject


    Чтобы изменить процесс сериализации в классе Person реализуем метод writeObject. Для модифицирования процесса десериализации определим в том же классе метод readObject. При реализации этих методов необходимо корректно восстановить данные.

    private void writeObject(ObjectOutputStream stream) throws IOException

    {

    // "Криптование"/скрытие истинного значения

    age = age << 2;

    stream.defaultWriteObject();

    }
    private void readObject(ObjectInputStream stream) throws IOException,

    ClassNotFoundException

    {

    stream.defaultReadObject();

    // "Декриптование"/восстановление истинного значения

    age = age >> 2;

    }

    В данных методах значение возраста age просто умножается на 4 при записи объекта, а при восстановлении - делится на четыре. Алгоритм, конечно же можно усложнить; в примере он представлен только для демонстрации возможностей сериализации.

    Сериализация и рефакторинг кода


    Сериализация позволяет вносить небольшие изменения в структуру класса, так что даже после рефакторинга класс ObjectInputStream по-прежнему будет с ним прекрасно работать. К наиболее важным изменениям, с которыми спецификация Java Object Serialization может справляться автоматически:

    • добавление новых полей в класс;

    • изменение полей из статических в нестатические;

    • изменение полей из транзитных в нетранзитные.

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

    Рефакторинг сериализованного класса


    Для тестирования сериализации с измененной структурой класса Person на основе предыдущего примера необходимо проделать следующие предварительные шаги :

    1. Создать файл данных с использованием метода setUpBeforeClass класса JUnitPerson и блокировкой удаления файла в методе tearDownAfterClass; можно закоментировать строку удаления файла.

    2. Блокировать создание файла данных в методе setUpBeforeClass класса JUnitPerson при следующем выполнении; также можно закоментировать строки создание файла.

    3. Изменить код класса Person, как это представлено в следующем листинге.

    Листинг изменений класса Person


    // Определение вне класса Person

    enum Gender { Male, Female }
    // Следующие изменения внутри класса Person
    // Переменная

    private Gender gender;
    // Методы get и set

    public Gender getGender() {

    return gender;

    }

    public void setGender(Gender gender) {

    this.gender = gender;

    }

    // Текстовое описание объекта

    public String toString() {

    return "[Person: firstName = " + firstName +

    ", lastName = " + lastName +

    ", gender = " + gender +

    ", age = " + age +

    ", spouse = " + spouse.getFirstName() + "]";

    }

    Теперь можно выполнить тест testSerialization класса JUnitPerson и увидеть, что тест прошел успешно, т.е. класс ObjectInputStream прочитал данные и объект был восстановлен корректно. При желании можно в конце кода testSerialization вставить строку

    fail(alex.toString());

    чтобы убедиться, что значения объекта восстановлены правильно, и что параметр gender равен null.
    1   ...   21   22   23   24   25   26   27   28   ...   39


    написать администратору сайта