3月21号

七、对象流

把一个对象持久化到物理介质,或者把对象传输到另一个独立的程序中,可以使用

JAVA 的对象流。

 

序列化:把对象保存到文件中,可以称为对象序列化到文件

反序列化:把对象从文件中读取到程序中,重新组装成对象,可以称为对象的反序

列化。

 

什么情况下,对象需要序列化:

1)对象要永久保存

2)对象要进行传输

 

JAVA中如何实现对象序列化:

1)把要进行序列化的类,实现Serializable标记接口

    此接口中无任何定义,目的是告诉虚拟机此类的对象需要被序列化

2)构造一个字节输入输出流

3)通过字节输入输出流构造对象流(ObjectOutputStream/ObjectInputStream

4)调用writeObject()/readObject()写入或读取对象

5)关闭流

 

注意:对象的反序列化操作,只能读取一次,同一个文件要写入多个对象,使用对象数组封装后写入,同一个文件不要出现多个不同类型的对象。

 

对象序列化过程:

把类名、属性的类型、属性的值以二进制方式写入文件保存,在需要的时候读取该文件

,再根据保存的信息重新创建一个对象到内存中,称为还原。

序列化不仅仅是把有用的属性值保存下来,还要保存类型和类信息。

 

在实现对象保存操作时,必须使用 Serializable方式的序列化

在实现对象传输操作时,如果使用Serializable方式的序列化,不是最优的方式,因为

这种方式会传输除了必须要的数据,还额外传输了类信息和属性信息,从这个点考虑

就是浪费内存。牺牲性能,降低传输效率。

 

八、字节数组流

ByteArrayInputStream: 字节数组输入流

ByteArrayOutputStream: 字节数组输出流

 

字节数组流内部维护一个缓冲区(字节数组),不关联文件,无需关闭,所有的操作

都基于内存。内部的缓冲区是一个动态数组(算法是原来长度*2

 

字节数组流的本质就是使用 IO 流的操作方式来管理动态数组。

 

private static void byteArrayStream(byte[] bytes){

 

ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

int count = 0;

int b = -1;

while((b=bais.read())!=-1){

if(b>=97 && b<=123){

count++;

}

}

System.out.println(count);

 

}

public static void main(String[] args) {

//统计一个文本中的字母个数

String info = "12832fdsjlfje3830fefefez";

byteArrayStream(info.getBytes());

}

 

九、数据流

DataInputStream/DataOutputStream: 数据输入输出流

JAVA基本数据类型形式,与底层机器无关,这样的好处是我们可以忽略底层操作系统

,按存储数据的大小来写入或读取数据。

 

OutputStream out = new FileOutputStream("c:\\test\\my.data");

DataOutputStream dos = new DataOutputStream(out);

dos.writeInt(10); //写入一个整数,按4个字节

dos.writeByte(1); //写入一个数,按1字节

//写入字符串时,会额外增加2个字节,用于表示字符串,

//字符按不定长计算(1-6

dos.writeUTF("moliying");  //写入一个字符串

 

读取时的顺序要和写入的顺序一致。

 

InputStream out = new FileInputStream("c:\\test\\my.data");

DataInputStream dis = new DataInputStream(out);

dis.readInt(); //4个字节读一个整数

dis.readByte(); //1字节读一个数

dis.readUTF();  //UTF 编码读取字符串

 

十、字符串流

StringReader

StringWriter

把一个字符串传入一个字符串流,好处是用流的形式来处理字符

内部操作都在内存中,无需关闭,不会有 IOException

 

例如,

 

XML/JSON 是数据传输的格式(最常见),用字符串来表示

xml:

<person id="1">

    <name>黄笙</name>

    <age>30</age>

    <sex>未知</sex>

</person>

 

JSON:

{'id':1,'name':'黄笙','age':30,'sex':'未知'}

 

//当连接服务器后,返回的数据以 JSON XML 字符串的格式,当我们接到这样的数据

//需要使用对应的技术去解析成JAVA 中的对象

private void parseJSON(String json){

 

    StringReader sr = new StringReader(json);

    //sr作为参数传入到对应数据解析器中

}

字符串流与字节数组流类似,都是内存操作流。

 

十一、RandomAccessFile

一个可以随机读写操作的工具类

RandomAccessFile ra = new RandomAccessFile(file,"rw");

//创建一个可读可写的RandomAccessFile对象

 

模式:

r:读模式

rw :读写模式

 

可以通过getFilePointer() 返回此文件中的当前偏移量。

seek(long pos)

设置到此文件开头测量到的文件指针偏移量,

在该位置发生下一个读取或写入操作。

skipBytes(int n) 尝试跳过输入的 n 个字节以丢弃跳过的字节。

 

十二、装饰者设计模式

问题:为了给一个对象附加额外的功能,使用直接继承的方式,会带来大量的子类,

造成难以维护,使用装饰者设计模式,可以让这样的关系更加灵活,并利于扩展。

 

意图:

动态地给一个对象添加一些额外的职责。就增加功能来说,

Decorator模式相比生成子类更为灵活。

该模式以对客户端透明的方式扩展对象的功能。

 

适用环境:

在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

处理那些可以撤消的职责。

当不能采用生成子类的方法进行扩充时。

一种情况是,可能有大量独立的扩展,

为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

 

装饰者设计模式的相关角色分配:

Component(被装饰对象基类)

定义对象的接口,可以给这些对象动态增加职责;

ConcreteComponent(具体被装饰对象)

定义具体的对象,Decorator可以给它增加额外的职责;

Decorator(装饰者抽象类)

维护指向Component实例的引用,定义与Component一致的接口;

ConcreteDecorator(具体装饰者)

具体的装饰对象,给内部持有的具体被装饰对象增加具体的

 

装饰者模式小结:

OO原则:动态地将责任附加到对象上。

想要扩展功能,装饰者提供有别于继承的另一种选择。

 

要点:

1、继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案。

2、在我们的设计中,应该允许行为可以被扩展,而不须修改现有的代码。

3、组合和委托可用于在运行时动态地加上新的行为。

4、除了继承,装饰者模式也可以让我们扩展行为。

5、装饰者模式意味着一群装饰者类,这些类用来包装具体组件。

6、装饰者类反映出被装饰的组件类型(实际上,他们具有相同的类型,

     都经过接口或继承实现)

7、装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,

     甚至将被装饰者的行为整个取代掉,而达到特定的目的。

8、你可以有无数个装饰者包装一个组件。

9、装饰者一般对组建的客户是透明的,除非客户程序依赖于组件的具体类型。

 

十三、常见编码格式

1iso-8859-1:单字节的编码格式,一般用于英文0-255之间

2GBK/GB2312:中文国际编码,以双字节的编码格式,GBK GB2312字符集更大

3unicodejava的默认编码,以双字节的编码格式,不兼容iso-8859-1,单字节也

    用双字节来表示。浪费存储空间。

4UTF-8:以不定长(1-6)字节的编码格式,可以表示国际上的所有文字,更有利于存储空间的合理利用。

通常情况下,在程序造成乱码的:

1)程序编码与本机编码不一致

2)客户端程序与服务器程序的编码不一致

 

转换编码的方式:

比如把一个iso-8859-1编码的字符串转成 GBK 编码

String s = new String(data.getBytes("iso-8859-1"),"GBK");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值