Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> ObjectOutputStream.replaceObject() 
:(
    Опции темы
leniviy
Дата 7.2.2012, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 552
Регистрация: 8.2.2003
Где: Спб

Репутация: нет
Всего: 5



Привет. Есть некий библиотечный класс "A", который плохо восстанавливается после сериализации (в нём неправильно использованы transient поля). 
Мне бы сделать так, чтобы ObjectOutputStream после "A" ещё дописывал кое-какую инфу.

Чтобы обойти это, я хочу переопределить ObjectOutputStream.replaceObject(Object) и ObjectInputStream.resolveObject(Object) , обернуть "A" в "B".

Проблема в том, что у класса "A" могут быть наследники, и я не знаю, как восстановить наследника со всеми его полями. Дело в том, что как только я заменил "A" на "B", ObjectOutputStream не будет пытаться сериализовать "A", то есть такой класс :
Код

class B {
  A a;
}

будет серилизован как:
$1=B{a=$1}
а не
$1=B{a=($2=A{}) }

Мне кажется, я не должен в replaceObject() заменять "A" на "B", а вместо этого переопределить какой-то другой метод, но не знаю, какой.

Вот рабочий пример
Код

package ru.sbrf.iask.server.controller.operation.op42;

import java.io.*;
import java.lang.reflect.Field;
import java.util.*;

import org.junit.Test;

import static org.junit.Assert.*;

public class CloneSerializableTest2 {

    // библиотечные классы
        public static class A implements Serializable {
            public transient String s1;
        }
    
        public static class MyA extends A {
    
            public String s2;
        }

    private static class AHolder implements Serializable {

        private static final Field s1Fld;

        static {
            try {
                s1Fld = A.class.getDeclaredField("s1");
                s1Fld.setAccessible(true);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException("Unexpected error", e);
            }
        }

        private String s1;
        private A a;

        public AHolder(A m) {
            this.a = m;
            try {
                s1 = (String)s1Fld.get(m);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Unexpected error", e);
            }
        }

        public void restoreA() {
            try {
                s1Fld.set(a, s1);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Unexpected error", e);
            }
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T cloneSerializable(T o) {
        try {
            final List<AHolder> accumSrc = new ArrayList<AHolder>();

            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bout) {
                {
                    enableReplaceObject(true);
                }
                @Override
                protected Object replaceObject(Object obj) throws IOException
                {
                    if (obj instanceof A) {
                        accumSrc.add(new AHolder((A)obj));
                    }
                    return super.replaceObject(obj);
                }
            };

            out.writeObject(o);
            out.writeObject(accumSrc);
            out.close();

            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
            ObjectInputStream in = new ObjectInputStream(bin);
            Object copy = in.readObject();
            List<AHolder> accumDst = (List<AHolder>)in.readObject();
            for (AHolder r : accumDst) {
                r.restoreA();
            }

            in.close();
            return (T)copy;
        } catch (IOException e) {
            throw new RuntimeException("Unexpected error", e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Unexpected error", e);
        }
    }

    @Test
    public void testIt() throws Exception {
        try {
        MyA m1 = new MyA();
        m1.s1 = "a";
        m1.s2 = "b";
        
        m1 = cloneSerializable(m1);

        assertEquals("a", m1.s1);
        assertEquals("b", m1.s2);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
}


Здесь мне мешают жить вот эти 4 строчки:
Код

out.writeObject(accumSrc);
...
List<AHolder> accumDst = (List<AHolder>)in.readObject();
for (AHolder r : accumDst) {
    r.restoreA();
}

Я хочу, чтобы вызовов writeObject() и readObject() было достаточно

Это сообщение отредактировал(а) leniviy - 7.2.2012, 13:28
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0457 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.