Java性能优化系列之五--JavaIO(二)

2014-11-23 23:56:40 · 作者: · 浏览: 1
保类的不同版本具有不同的serialVersionUID。

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