2)、java有很多基础类已经实现了serializable接口,比如string,vector等。但是比如hashtable就没有实现serializable接口。
3)、并不是所有的对象都可以被序列化。由于安全方面的原因一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现.
4)、反序列化对象时,并不会调用该对象的任何构造方法,仅仅是根据所保存的对象的状态信息,在内存中重新构建对象!
5)、当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量
6)、如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存!这是能用序列化解决深拷贝的重要原因。
(8)序列化与单例模式的冲突解决办法:
另外还有两个自定义序列化方法writeReplace和readResolve,分别用来在序列化之前替换序列化对象 和 在反序列化之后的对返回对象的处理。一般可以用来避免singleTon对象跨jvm序列化和反序列化时产生多个对象实例,事实上singleTon的对象一旦可序列化,它就不能保证singleTon了。JVM的Enum实现里就是重写了readResolve方法,由JVM保证Enum的值都是singleTon的,所以建议多使用Enum代替使用writeReplace和readResolve方法。
Java代码
private Object readResolve()
{
return INSTANCE;
}
private Object writeReplace(){
return INSTANCE;
}
注:writeReplace调用在writeObject前;readResolve调用在readObject之后。
(9)序列化解决深拷贝的代码:
public Object deepClone() throws IOException, OptionalDataException,
ClassNotFoundException {
// 将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this); // 从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
}
对象所属的类要实现Serializable接口。同时将该方法写入到对象所属的类中。
深拷贝的时候,调用该方法即可。
2、JavaIO中的装饰模式:

Java中使用的最广泛的装饰器模式就是JavaIO类的设计。比如,OutPutStream是输出流的基类,其子类有FileOutputStream 和FilterOutputStream,而FilterOutputStream的子类有BufferedOutputStream和DataOutputStream两个子类。其中,FileOutputStream为系统的核心类,它实现了向文件写数据的功能,使用DataOutputStream可以在FileOutputStream的基础上增加多种数据类型的写操作支持(DataOutputStream类中有writeUTF、writeInt等函数),而BufferdOutputStream装饰器可以对FileOutputStream增加缓冲功能,优化I/O性能。
3、JavaIO流的使用场景:
(1)IO流:用于处理设备上的数据,这里的设备指的是:硬盘上的文件、内存、键盘输入、屏幕显示。
(2)字节流和字符流:字节流好理解,因为所有格式的文件都是以字节形式硬盘上存储的,包括图片、MP3、avi等,因此字节流可以处理所有类型的数据。字符流读取的时候读到一个或多个字节时(中文对应的 字节数是两个,在UTF-8码表中是三个字节)时,先去查指定的编码表,将查到的字符返回。字符流之所以出现,就是因为有了文件编码的不同,而有了对字符进行高效操作的字符流对象。因此,只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都使用字节流。
(3)流操作的基本规律:
1)、明确数据源和数据汇,目的是明确使用输入流还是输出流。
2)、明确操作的数据是否是纯文本数据。
3)、是否需要进行字节流和字符流的转换。
4)、是否需要使用缓存。
(4)实例说明流操作的基本流程:把键盘上读入的数据以指定的编码存入到文件中。
1)、明白数据源:键盘输入,System.in,可用InputStream和Reader
2)、发现System.in对应的流是字节读入流,所以要将其进行转换,将字节转换为字符。
3)、所以要使用InputStreamReader转换流
4)、如果想提高效率,要加入缓存机制,那么就要加入字符流的缓冲区。BufferedReader,因此前四步构造出的输入流为:
BufferedReader bur = new BufferedReader(new InputStreamReader(System.in));
5)、明白数据汇:既然是数据汇,则一定是输出流,可以用OutputStream或Writer。
6)、往文件中存储的都是文本文件,因此选用Writer。
7)、因为要指定编码表,所以使用Writer中的转换流,OutputStreamWriter。
注意:虽然最终是文件,但是不可以选择FileWriter,因为该对象是使用默认编码表。
8)是否要提高效率,选择BufferedWriter。
9)转换输出流需要接收一个字节输出流进来,所以要是用OutputStream体系,而最终输出到一个文件中。那么就要使用OutputStream体系中可以操作的文件的字符流对象,FileOutputStream。
10)、通过前面的分析,得到的输出流对象如下:
//String charSet = System.getProperty("file.encoding");
String charSet = "utf-8";
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream("a.txt"),charSet);
4、可以和流相关联的集合对象Properties。
Map
|--HashTable
|--Properties
Properties:该集合不需要泛型,因为该集合中的键值都是String类型。
5、其他流对象:
(1)打印流:
P