Чтобы сделать одноэлементный класс, реализованный с использованием любого из предыдущих подходов, сериализуемым (глава 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