趣文网 > 作文大全

程序员:Java对象流 字节流 文件流的Serializable和深拷贝

2020-12-02 04:20:01
相关推荐

在Java中是指计算中流动的缓冲区,从外部设备流向中央处理器的数据流成为“输入流”,反之成为“输出流”。

字符流和字节流的主要区别:

字节流读取的时候,读到一个字节就返回一个字节;字符流使用了字节流读到一个或多个字节时。先去查指定的编码表,将查到的字符返回。字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。

Serializable接口概述

有时候我们有一种需求,保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且想把保存的对象状态再读出来,这样既可以实现对象的传递。

实现这一需求的方式有很多,比如,使用objectMapper序列化为Json字符串/对象,再进行传递或者保存,Java的设计指出也考虑到了这种需求,就设计出了Serializable接口,该接口没有必要实现的方法,默认继承了该接口后会就能自动调用java默认的序列化和放序列化。

Serializable接口代码实践

定义一个类用于序列化:UserInfo .java

@Getter

@Setter

public class UserInfo implements Serializable{ //实现Serializable接口才能被序列化

private String userName;

private String usePass;

private transient int userAge;//使用transient关键字修饰的变量不会被序列化

public UserInfo() {

userAge=20;

}

public UserInfo(String userName, String usePass, int userAge) {

super();

this.userName = userName;

this.usePass = usePass;

this.userAge = userAge;

}

@Override

public String toString() {

return "UserInfo [userName=" + userName + ", usePass=" + usePass + ",userAge="+(userAge==0?"NOT SET":userAge)+"]";

}

/**

* 静态方法,序列化对象到文件

* @param fileName

*/

public static void serialize(String fileName){

try {

//对象输出流和文件输出流结合使用,实现将对象持久化/序列化到本地

ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));

out.writeObject("序列化的日期是:");//序列化一个字符串到文件

out.writeObject(new Date());//序列化一个当前日期对象到文件

UserInfo userInfo=new UserInfo("郭大侠","961012",21);

out.writeObject(userInfo);//序列化一个会员对象

out.close(); //资源释放要放到finally中,这里并不规范

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 静态方法,从文件中反序列化对象

* @param fileName

*/

public static void deserialize(String fileName){

try {

ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));

String str=(String) in.readObject();//刚才的字符串对象

Date date=(Date) in.readObject();//日期对象

UserInfo userInfo=(UserInfo) in.readObject();//会员对象

System.out.println(str);

System.out.println(date);

System.out.println(userInfo);

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

主方法,运行实验一下:

class Main{

public static main(String[] args){

UserInfo.serialize("test");

sleep(2*60*1000)

UserInfo.deserialize("test");//这里userAge取读不到是因为使用了transient修饰,所以得到的是默认值

/**

* UserInfo的无参构造中给userAge属性赋值蛋反序列化得到的结果还是一样。

* 得出结论:

* 当从序列化的文件中读出某个类的实例时,实际上并不会执行这个类的构造函数,

* 而是载入了一个该类对象的持久化状态,并将这个状态赋值给该类的另一个对象。

*/

}

}

}

原始输出:

序列化的日期是:

Sun Dec 15 11:13:05 CST 2019

UserInfo [userName=郭大侠, usePass=961012,userAge=NOT SET]

基于字节流、对象流的深拷贝

public class Main {

public static void main(String[] args) throws IOException, ClassNotFoundException {

UserInfo userInfo1 = new UserInfo("123", "456", 111);

System.out.println(userInfo1);

UserInfo userInfo2 = deepClone(userInfo1);

System.out.println(userInfo2);

}

@SuppressWarnings("unchecked")

public static T deepClone(T object) throws IOException, ClassNotFoundException {

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

objectOutputStream.writeObject(object);

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);

return (T) objectInputStream.readObject();

/*

原始输出:

UserInfo [userName=123, usePass=456,userAge=111]

UserInfo [userName=123, usePass=456,userAge=NOT SET]

*/

}

}

从原始输出可以看出,transient 关键字可以可以抑制Object输入输出流对实例被transient 修饰属性的读写。

总结

以上两种应用场景,本质上Object输入输出流和其他输入输出流的配合使用:

和字节数组输入输入输出流配合使用,实现了对象的深拷贝和文件输入输出流的配合使用,实现了对象持久化到的本地文件再进行读取的功能

阅读剩余内容
网友评论
相关内容
延伸阅读
小编推荐

大家都在看

写作文软件 600字叙事作文 友谊英语作文 交警 作文 清廉作文 购物英语作文 冲突作文 作文万能结尾 作文我的弟弟 五上作文 四年级小学生作文 谦虚作文 一篇作文400字 最珍贵作文 身影作文 枫叶作文 写作业的作文 温暖600字作文 一束光作文 小鸭子作文 思辨作文 好作文开头 我的朋友作文英语 写父母的作文 一棵树作文 星空的作文 被打作文 1字作文 作文500字初一 我们作文600字