魔域java_java序列化

Java序列化Serialize

序列化与反序列化

序列化:把对象写入到流中

反序列化:把对象从流中读取出来

什么情况下序列化

对象需要通过网络进行传输

需要持久化对象到磁盘

需要持久化对象到数据库(把对象通过字节流的方式存储)

序列化的实现方式

实现Serializable接口

Serializable是一个标记接口,接口中没有任何方法

需要序列化的对象除基本数据类型属性外其他属性也必须实现Serializable接口

public class Student implements Serializable{

private static final long serialVersionUID = 2992794326818594180L;

private String name;

private int age;

//省略constructor、setter、getter、toString

}

@Test

public void test1() throws Exception {

Student s1=new Student("tom",20);

System.out.println(s1);

ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt"));

oos.writeObject(s1);

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt"));

Student s2=(Student)ois.readObject();

System.out.println(s2);

}

输出:

Student [name=tom, age=20]

Student [name=tom, age=20]

如果序列化对象的非基本数据类型属性没有实现Serialize接口,会抛出NotSerializableException异常

public class Student implements Serializable{

private static final long serialVersionUID = 2992794326818594180L;

private String name;

private int age;

private School school;

//省略constructor、setter、getter、toString

}

class School{

private String name;

//省略constructor、setter、getter、toString

}

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

Student s1=new Student("tom",20,new School("xw"));

System.out.println(s1);

ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt"));

oos.writeObject(s1);

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt"));

Student s2=(Student)ois.readObject();

System.out.println(s2);

}

输出:

java.io.NotSerializableException: com.moyuduo.analyze.School

实现Externaliable接口并实现方法

序列化对象的非基本数据类型外其他类型必须实现Serializable接口或Externaliable接口

实现Externaliable的类必须提供无参构造器,因为在反序列化的时候需要使用无参构造器创建对象

这种方式比实现Serializable接口略复杂,但是可以实现更加复杂的控制,因为实现Externaliable接口重写方法需要我们自己指定序列化规则(可以对序列化进行加密产生字节)和反序列化规则(序列化规则的逆过程)

实现Externaliable接口方式比实现Serializable接口方式的效率高

public class Student implements Externalizable{

private String name;

private int age;

private School school;

public Student() {//必须加无参构造器

System.out.println("Student无参构造器");

}

//省略有参constructor、setter、getter、toString

@Override

public void writeExternal(ObjectOutput out) throws IOException {

out.writeObject(new StringBuffer(this.name).reverse().toString());

out.writeInt(this.age);

out.writeObject(this.school);

}

@Override

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

this.name=new StringBuffer((String)in.readObject()).reverse().toString();

this.age=in.readInt();

this.school=(School)in.readObject();

}

}

class School implements Externalizable{

private String name;

public School() {

System.out.println("School无参构造器");

}

//省略有参constructor、setter、getter、toString

@Override

public void writeExternal(ObjectOutput out) throws IOException {

out.writeObject(new StringBuffer(this.name).reverse().toString());

}

@Override

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

this.name=new StringBuffer((String)in.readObject()).reverse().toString();

}

}

public static void main(String[] args) throws Exception {

Student s1=new Student("tom",20,new School("xh"));

System.out.println(s1);

ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt"));

oos.writeObject(s1);

oos.close();

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt"));

Student s2=(Student)ois.readObject();

System.out.println(s2);

ois.close();

}

输出:

Student [name=tom, age=20, school=School [name=xh]]

Student无参构造器

School无参构造器

Student [name=tom, age=20, school=School [name=xh]]

部分属性序列化

使用transient关键字

被transient关键字修饰的属性,在对象序列化时不会序列化,而且反序列化得到的该属性值是默认值

public class Student implements Serializable{

private static final long serialVersionUID = 1L;

private String name;

private transient int age;

//省略constructor、setter、getter、toString

}

public static void main(String[] args) throws Exception{

Student s=new Student("tom",20);

System.out.println(s);

ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt"));

oos.writeObject(s);

oos.close();

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt"));

Student s2=(Student)ois.readObject();

System.out.println(s2);

ois.close();

}

输出:

Student [name=tom, age=20]

Student [name=tom, age=0]

自定义属性序列化

可以实现Externalizable接口并在序列化方法writeExternal中序列化需要的属性

可以实现Serializable接口,并自己定义

private void writeObject(java.io.ObjectOutputStream out) throws IOException;

private void readObject(java.io.ObjectInputStream in) throws IOException,ClassNotFoundException;

private void readObjectNoData() throws ObjectStreamException;

writeObject方法序列化需要的属性

public class Student implements Serializable{

private static final long serialVersionUID = 1L;

private String name;

private int age;

//省略constructor、setter、getter、toString

private void writeObject(ObjectOutputStream out) throws IOException{

out.writeObject(this.name);

}

private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException{

this.name=(String)in.readObject();

}

}

public static void main(String[] args) throws Exception{

Student s=new Student("tom",20);

System.out.println(s);

ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt"));

oos.writeObject(s);

oos.close();

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt"));

Student s2=(Student)ois.readObject();

System.out.println(s2);

ois.close();

}

输出:

Student [name=tom, age=20]

Student [name=tom, age=0]

序列化对象的static属性

在对象进行序列化时,被static修饰的属性并不会进行序列化

public class Student implements Serializable{

private static final long serialVersionUID = 1L;

private String name;

public static int age;

//省略constructor、setter、getter、toString

}

public static void main(String[] args) throws Exception{

Student s=new Student("tom");

Student.age=20;

System.out.println(s);

ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt"));

oos.writeObject(s);

oos.close();

Student.age=30;

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt"));

Student s2=(Student)ois.readObject();

System.out.println(s2);

ois.close();

}

输出:

Student [name=tom,age=20]

Student [name=tom,age=30]

可以看到Student的static属性age并没有被序列化输出

实现Serializable的类需要提供一个serialVersionUID

serialVersionUID是用于确定版本信息的,如果不指定JVM会根据类信息自动生成一个,JVM会根据两个serialVersionUID判断是否是同一个类,如果serialVersionUID不一致,会抛出InvalidClassException异常

一般建议显式指定serialVersionUID,如果类中添加了新的属性,而想进行向下兼容的话,可以不改变serialVersionUID,那么反序列化后新添加的属性就是默认值

如果删除了类的属性,就需要修改serialVersionUID

public class Student implements Serializable{

private static final long serialVersionUID = 1L;

private String name;

private int age;

//省略constructor、setter、getter、toString

}

//把对象写出去

@Test

public void test4() throws IOException {

Student s=new Student("tom",20);

System.out.println(s);

ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt"));

oos.writeObject(s);

oos.close();

}

//删除Student的age属性,并修改serialVersionUID

public class Student implements Serializable{

private static final long serialVersionUID = 2L;

private String name;

//省略constructor、setter、getter、toString

}

//读取对象

public static void main(String[] args) throws Exception{

Student s=new Student("tom");

ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt"));

Student s2=(Student)ois.readObject();

System.out.println(s2);

ois.close();

}

输出:

Exception in thread "main" java.io.InvalidClassException: com.moyuduo.analyze.Student; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值