IO
字节流
InputStream
() FileInputStream 从文件读取字节
() BufferedInputStream 加入缓冲功能,提高文件的读取效率
ByteArrayInputStream 从字节数组变成输入流
OutputStream
() FileOutputStream 向文件写入字节
() BufferedOutputStream 加入缓冲功能, 提高文件的写入效率
ByteArrayOutputStream 把流的内容写入字节数组
PrintStream 实际上就是 System.out
字符流
Reader
() InputStreamReader 转换字节流为字符流
() BufferedReader 功能增强,以行为单位读取数据 (装饰器模式)
FileReader 是InputStreamReader子类,将字符编码固定为操作系统的默认编码,不能手工改动
Writer
() OutputStreamWriter 转换字节流为字符流
() PrintWriter 以行为单位写入数据
write 当成字符写入
print print就是将参数转为字符串后写入
FileWriter 是OutputStreamWriter的子类,也是固定了字符编码
java中的序列化
问题:如何将对象中的信息永久保存
1.将来将对象信息存入数据库
2.java 中提供的序列化方式来永久保存数据
首先要让类实现Serializable序列化接口
第二使用ObjectOutputStream 写入要序列化的对象
java 31行
public class Student implements Serializable{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```java
Student student = new Student();
student.setId(1);
student.setName("张三");
// 序列化就是将对象变为输出字节流
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:\\student.obj"));
os.writeObject(student);
os.close();
如果没有实现Serializable接口,会出现NotSerializableException
注意:
1)要求对象中的所有属性也都是可以序列化
2)如果某个属性不想序列化,可以在属性上加transient
关键字
反序列化
把字节内容读取进来,还原为java对象
ObjectInputStream用来读取字节内容,还原(反序列化)为java对象
java 6行
ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:\\student.obj"));
Student s = (Student)is.readObject();
System.out.println(s.getId());
System.out.println(s.getName());
System.out.println(s.getAddress());
除了可以写入和读取对象以外,还可以写入和读取基本类型(int,long,boolean...) ,读取和写入的顺序要保持一致
如果不一致,出现EOFException
如果没有更多内容,也会出现EOFException
建议在写入时最后一个对象使用null,这样读取时就可以根据null来判断是否读取完毕
序列化和反序列化其实也是java中的一种数据传输的机制
创建对象的几种方式:
- 反序列化
- clone 是一种
- new 是一种
克隆需要实现Cloneable接口,并覆盖clone方法,克隆举例:
java 40行
public class Teacher implements Cloneable{ // 可克隆的
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// 必须调用Object父类的克隆方法
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Teacher t = new Teacher();
t.setId(1);
t.setName("满老师");
Teacher t2 = (Teacher)t.clone();
System.out.println(t2.getId());
System.out.println(t2.getName());
System.out.println(t2 == t);
}
}
克隆对应的设计模式:原型(prototype)模式 ,不走构造方法,根据一个已有对象创建新的对象。
使用Cloneable接口和clone克隆的对象,仅仅是浅拷贝
,如果属性为引用类型,复制的仅是地址。没有为这个属性创建新的对象
深拷贝
利用序列化和反序列化生成新的对象,也会为属性创建新的对象
例:
java 61行
public class Teacher2 implements Serializable{
private int id;
private String name;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher2 clone() {
try {
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(this); // 写入当前对象
byte[] bytes = bos.toByteArray(); // 字节结果
// 反序列化
ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(bytes));
Teacher2 t = (Teacher2)is.readObject();
return t;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
Teacher2 t = new Teacher2();
t.setId(1);
t.setName("满老师");
t.setBirthday(new Date());
Teacher2 t2 = t.clone();
System.out.println(t == t2);
System.out.println(t.getBirthday() == t2.getBirthday());
}
}