Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока
Скачать 1.93 Mb.
|
Особенности сериализации DateЕсли объект сериализации включает поля типа Date, то здесь следует, при необходимости, учитывать временной сдвиг между различными регионами. В противном случае может возникнуть ситуация, при которой на сервере будет создан объект Date с одним временем в определенной TimeZone, а на клиенте он будет десериализован с другой TimeZone. В зависимости от времени создания игнорирование TimeZone может привести к изменению даты. Решение данной проблемы представлено на странице описания TimeZone. Использование сериализацииТехнология RMI (Java Remote Method Invocation), построенная на сериализации, позволяет java-приложению, запущенному на одной виртуальной машине, вызвать методы объекта, работающего на другой виртуальной машине JVM (Java Virtual Machine). 12) Клонирование объекта. Глубокое и поверхностное. Для клонирования объекта в Java можно пользоваться тремя способами: Переопределение метода clone() и реализация интерфейса Cloneable(); Использование конструктора копирования; Использовать для клонирования механизм сериализации Теперь по порядку. Первый способ подразумевает, что вы будете использовать механизм так называемого «поверхностного клонирования» и сами позаботитесь о клонировании полей-объектов. Метод clone() в родительском классе Object является protected, поэтому требуется переопределение его с объявлением как public. Он возвращает экземпляр объекта с копированными полями-примитивами и ссылками. И получается что у оригинала и его клона поля-ссылки указывают на одни и те же объекты. Пример далее показывает, как одновременно меняется поле у оригинального объекта и клона. public class CloneTest{ static class Person implements Cloneable{ String name; int age; Car car; Person(Car car,int age,String name) { this.car = car; this.age = age; this.name = name; } @Override public String toString() { return this.name+" {" + "age=" + age + ", car=" + car + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } static class Car{ public String color; Car(String color) { this.color = color; } @Override public String toString() { return "{" + "color car='" + color + '\'' + '}'; } } public static void main(String[] args) throws CloneNotSupportedException { Car car = new Car("Green"); Person person=new Person(car,25,"Mike"); Person clone = (Person) person.clone(); System.out.println(person); System.out.println(clone); clone.name=new String("Ivan"); clone.car.color="red"; System.out.println(person); System.out.println(clone); } } Вывод: Mike {age=25, car={color car='Green'}} Mike {age=25, car={color car='Green'}} Mike {age=25, car={color car='red'}} Ivan {age=25, car={color car='red'}} Из примера выше видно, что у клона и оригинала состояние одного из полей изменяется одновременно. Следующий способ заключается в использовании конструктора копирования: public class Person { private int age; private String name; public Person(int age, String name){ this.age=age; this.name=name; } // конструктор копии public Person(Person other) { this(other.getAge(), other.getName()); } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + '}'; } public static void main(String[] args) { Person original = new Person(18, "Grishka"); Person clone = new Person(original); System.out.println(original); System.out.println(clone); } } Вывод: Person{age=18, name='Grishka'} Person{age=18, name='Grishka'} В классе описывается конструктор, который принимает объект этого же класса и инициализирует значениями его полей поля нового объекта. О реализации инициализации полей полностью должен позаботиться разработчик класса. Но оба вышеуказанных способа полны потенциальных ошибок и по сути создают копию объекта. Наиболее удобным и гибким способом клонирования является механизм сериализации. Он заключается в сохранении объекта в поток байтов с последующей эксгумацией его от туда. Для примера пригласим кота Ваську, его ждёт пара опытов: import java.io.*; class Cat implements Serializable{ private String name; private String color; private int age; public Cat(String name, String color, int age) { this.name = name; this.color = color; this.age = age; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + ", color='" + color + '\'' + ", age=" + age + '}'; } } public class BasketCats{ public static void main(String[] args) throws IOException, ClassNotFoundException { Cat vaska = new Cat("Vaska","Gray",4); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream ous = new ObjectOutputStream(baos); //сохраняем состояние кота Васьки в поток и закрываем его(поток) ous.writeObject(vaska); ous.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); //создаём кота для опытов и инициализируем его состояние Васькиным Cat cloneVaska = (Cat)ois.readObject(); System.out.println(vaska); System.out.println(cloneVaska); System.out.println("*********************************************"); cloneVaska.setColor("Black"); //Убеждаемся что у кота Васьки теперь есть клон, над которым можно ставить опыты без ущерба Василию System.out.println(vaska); System.out.println(cloneVaska); } } Вывод: Cat{name='Vaska', color='Gray', age=4} Cat{name='Vaska', color='Gray', age=4} ********************************************* Cat{name='Vaska', color='Gray', age=4} Cat{name='Vaska', color='Black', age=4} Ни один кот не пострадал в результате тестов, мы видим что Васька был сохранён в поток, из которого затем восстановили независимый клон. Если нет особой необходимости обработки полей во время клонирования объектов, то сериализация является наиболее предпочтительным вариантом для этих целей. |