Зачем объявлять все поля экземпляра переходными в синглтонах?

Чтобы сделать одноэлементный класс, реализованный с использованием любого из предыдущих подходов, сериализуемым (глава 11), недостаточно просто добавить в его объявление реализацию Serializable. Чтобы сохранить гарантию одноэлементности, вы должны объявить все поля экземпляра переходными и предоставить метод readResolve (статья 77). В противном случае каждый раз при десериализации сериализованного экземпляра будет создаваться новый экземпляр.

Что приводит к моему вопросу: зачем объявлять все поля экземпляра переходными? Я думаю, что readResolve достаточно! мой вопрос: почему автор сказал, что мы должны объявлять все поля экземпляра переходными в синглтонах

package com.effective.test;

import java.io.Serializable;

public class NormalBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private  transient  int id;

    /**
     * no matter declare transient or not...nothing is different!why author say that??
     */
    private/* transient */String name;

    private NormalBean(int id, String name) {
        this.id = id;
        this.name = name;
    }

    private static final NormalBean INSTANCE = new NormalBean(12345,"jack");

    public static NormalBean getInstance() {
        return INSTANCE;
    }

    /*
     * The readResolve method is called when ObjectInputStream has read an
     * object from the stream and is preparing to return it to the caller.
     * ObjectInputStream checks whether the class of the object defines the
     * readResolve method. If the method is defined, the readResolve method is
     * called to allow the object in the stream to designate the object to be
     * returned.
     * 
     * And in Singleton case we are returning the same instance that was created
     * while classloading and no new instances are returned. So singletonness is
     * maintained.
     */
    private Object readResolve() {
        return INSTANCE;
    }

    @Override
    public String toString() {
        return "NormalBean [id=" + id + ", name=" + name + ", getClass()=" + getClass() + ", hashCode()=" + hashCode()
                + "]";
    }
}

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class TestTransientPlusReadResolve {
      NormalBean bean=NormalBean.getInstance() ;
    public   void writeAndRead() throws IOException {
        ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream("writeAndRead.txt"));
        System.out.println("this is the one "+bean );

        outStream.writeObject(bean);
        outStream.close();
        try {
            Thread.sleep(500l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("writeAndRead.txt"));

        try {
            NormalBean backBean = (NormalBean) inputStream.readObject();
            System.out.println("this is the one "+backBean );

            System.out.println("still the One?"+(backBean==bean));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            inputStream.close();
        }
    }

    public static void main(String[] args) throws IOException {
      new TestTransientPlusReadResolve().writeAndRead();
    }

}

Выход:

    this is the one NormalBean [id=12345, name=jack, getClass()=class com.effective.test.NormalBean, hashCode()=366712642]

    this is the one NormalBean [id=12345, name=jack, getClass()=class com.effective.test.NormalBean, hashCode()=366712642]

    still the One?true

person user3003728    schedule 03.05.2015    source источник
comment
зачем объявлять все поля экземпляра переходными? Я думаю, что readResolve достаточно!   -  person user3003728    schedule 03.05.2015
comment
Как будет сохранен экземпляр в следующем случае: загрузить jvm, записать класс в файл, выгрузить jvm, загрузить jvm, перезагрузить класс из файла?   -  person engineercoding    schedule 03.05.2015
comment
мой вопрос: почему автор сказал, что мы должны объявлять все поля экземпляра переходными в синглтонах   -  person user3003728    schedule 03.05.2015
comment
Не используйте форматирование кавычек для текста, который не заключен в кавычки, и используйте его для текста, который есть цитируется. Ваш вопрос был совершенно непонятен из-за злоупотребления предоставленными средствами форматирования. И когда вы что-то цитируете, указывайте цитату.   -  person user207421    schedule 03.05.2015


Ответы (3)


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

Это также имеет соображение производительности. Если вам не нужно сериализовать значения полей, потому что они одинаковы для синглтона, зачем вам его сериализовать, то, например. отправить его по сети, а затем выполнить readResolve только для того, чтобы игнорировать полученные значения?

person molnargab    schedule 03.05.2015
comment
мой вопрос: почему автор сказал, что мы должны объявлять все поля экземпляра переходными в синглтонах - person user3003728; 03.05.2015

(Глава 11)

Глава 11 чего?

Чтобы сохранить гарантию синглтона, вы должны объявить все поля экземпляра переходными.

Нет, не знаешь. Создание переменных экземпляра transient не требуется для обеспечения одноэлементной гарантии. Предоставления метода readResolve() достаточно.

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

Какой автор? Автор чего? Где он это сказал? Каковы были его точные слова? Какой у Вас вопрос?

Возможно, он предложил это для повышения производительности, поскольку сериализация данных, которые не будут использоваться, — просто пустая трата времени и места.

person user207421    schedule 03.05.2015
comment
Эффективная Ява. - person Baroudi Safwen; 07.10.2019

Если вы помечаете переменную экземпляра как переходную, вы указываете JVM пропускать (игнорировать) эту переменную при попытке сериализовать содержащий ее объект. Сериализация — одна из самых крутых возможностей Java; он позволяет сохранять (иногда это называют «выравниванием») объекта, записывая его состояние (другими словами, значение его переменных экземпляра) в поток ввода-вывода специального типа. С помощью сериализации вы можете сохранить объект в файл или даже отправить его по сети для повторного заполнения (десериализации) на другом конце, в другой JVM.

person Mohan Raj    schedule 03.05.2015