Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Как сериализовать/десериализовать объект который содержит другой объект?

#java #serializable #classloader


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

Например, класс Foo с Bar объектом внутри.

class Foo implements Serializable {
    Bar bar;
}


Класс Bar

class Bar implements Serializable {
    String s = "test"
}


сначала делаю сериализацию для объекта:

Foo foo = new Foo();
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
writeObject(foo);
flush();
close();


получаю бинарный файл с объектом, а как мне передать и загрузить классы, чтобы можно
было прочитать этот файл?
    


Ответы

Ответ 1



Как то так: import java.io.*; public class Foo implements Serializable { private Bar bar; private Foo() { bar = new Bar(); } public static void main(String[] args) { String filename = "foo.ser"; Foo foo = new Foo(); try (FileOutputStream fos = new FileOutputStream(filename); ObjectOutputStream out = new ObjectOutputStream(fos)) { out.writeObject(foo); } catch (Exception ex) { ex.printStackTrace(); } Bar bar = null; try (FileInputStream fis = new FileInputStream(filename); ObjectInputStream in = new ObjectInputStream(fis)) { bar = ((Foo) in.readObject()).getBar(); } catch (Exception ex) { ex.printStackTrace(); } System.out.println(bar.getText()); } private Bar getBar() { return bar; } } class Bar implements Serializable { private String text; Bar() { text = "test"; } public String getText() { return text; } }

Ответ 2



Сериализация и так всегда сохраняет тип объекта. Так что, если Foo и Bar доступны компилятору читающего кода, всё просто: Object o = oin.readObject(); Foo f = null; Bar b = null; if (o instanceof Foo) f=(Foo) o; if (o instanceof Bar) b=(Bar) o; или if (o.getClass()==Foo.class) f=(Foo) o; Если классы Foo/Bar недоступны читающему коду в принципе, то при чтении будет ClassNotFoundException . Теоретически, сами Foo.class и Bar.class сериализуются, но передать их потом в ObjectInputStream - отдельная история. Например, говорят, что можно переопределить метод ResolveClass: https://community.oracle.com/thread/1151865 , но это не готовое решение.

Ответ 3



Файл будет десереализован в объект типа вашего класса, потом можно с помощью .getClass() получить класс объекта, если он вам действительно нужен Если необходимо просто десереализовать объект то для этого нет необходимости предварительно получать класс будущего объекта если же нужно потом вызвать метод этого объекта, при чем у вас нет ни интерфейса ни класса объекта то стоит посмотреть в сторону Class c = obj.getClass(); Method m = c.getDeclaredMethod("methodName"); m.invoke(obj);

Комментариев нет:

Отправить комментарий