欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java学习记录分享(十一)

程序员文章站 2022-10-03 15:49:34
序列化和反序列化序列化就是指把Java对象转换为字节序列的过程,反序列化就是指把字节序列恢复为Java对象的过程。如果直接使用io流的知识来实现,会发现一旦对象的属性过多之后,代码的繁琐程度大大增加,所以采用序列化方法。下面这个例子就是对Person对象的三个属性进行存储,如果属性过多那么注释行代码会很庞大(此处省略Person类)import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.Fi...

序列化和反序列化

	序列化就是指把Java对象转换为字节序列的过程,
	反序列化就是指把字节序列恢复为Java对象的过程。
	如果直接使用io流的知识来实现,会发现一旦对象的属性过多之后,代码的繁琐程度大大增加,所以采用序列化方法。
	下面这个例子就是对Person对象的三个属性进行存储,如果属性过多那么注释行代码会很庞大(此处省略Person类)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class NotSeralizeTest {
		public static void main(String[] args) {
			Person person=new Person("jack",22,"襄阳");
			savePerson(person);
			Person person2=loadPerson();
			System.out.println(person==person2);//打印结果为false,因为重新new了一个
}
private static Person loadPerson() {
	BufferedReader reader = null;
	try {
		reader=new BufferedReader(new FileReader("D:/person2.dat"));
		String content=reader.readLine();
		String[] arr= content.split("_");
		Person person=new Person(arr[0],Integer.parseInt(arr[1]),arr[2]);
		System.out.println(person);
		return person;	
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}catch (IOException e) {
		e.printStackTrace();
	}finally {
		try {
			reader.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	return null;
}
private static void savePerson(Person person) {
	String content=person.getName()+"_"+person.	getAge()+"_"+person.getAddress();
	BufferedWriter bw=null;
	
	try {
		bw=new BufferedWriter(new FileWriter("D:/person.dat"));
		bw.write(content);
		bw.flush();
	} catch (IOException e) {
		e.printStackTrace();
	}finally {
		try {
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	}
}
	序列化过程,要让想要被保存的对象的类实现Seralizable,这个接口是个标识接口,是表面该类可以被序列化,不需要实现
	该接口的方法,因为这个接口中没有一个方法。java中一共有4个这样的标识接口。简单介绍一下
	java.io.Serializable:未实现此接口的类将无法使其任何状态序列化或反序列化.为保证 serialVersionUID 值跨不同 
java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值.
	java.lang.Cloneable:表明Object.clone()方法可以合法地对该类实例进行按字段复制.实现此接口的类应该使用公共
方法写 Object.clone(它是受保护的).如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 
CloneNotSupportedException 异常.
	java.util.RandomAccess:用来表明其支持快速(通常是固定时间)随机访问.此接口的主要目的是允许一般的算法更改
其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能.
	java.rmi.Remote:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口.任何远程对象都必须直接或间接实现
此接口.只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用.
现在用序列化的方式来存储Person对象。
public class SerializeTest {
		public static void main(String[] args) {
			Person person = new Person("jim",20,"哈尔滨");	
			ObjectOutputStream oos=null;
			try {
				
				oos=new ObjectOutputStream(new FileOutputStream("D:/person3.dat"));
				oos.writeObject(person);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
}

Person.java

public class Person implements Serializable{
	//实现Serializable接口标识类
	private static final long serialVersionUID = 1L;
	//如果一个类标识为可序列化的类,那么要给这个类一个默认的UID供jdk识别
		private String name;
		private int age;
		private String address;
		public Person() {
			super();
		}
		public Person(String name, int age, String address) {
			super();
			this.name = name;
			this.age = age;
			this.address = address;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public String getAddress() {
			return address;
		}
		public void setAddress(String address) {
			this.address = address;
		}
		@Override
		public String toString() {
			return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
		}
}
	只需要new一个对象输出流即可,调用writeObject()方法。
	说明一下private static final long serialVersionUID = 1L;这条语句的作用,
	JAVA序列化的机制是通过判断类的serialVersionUID来验证的版本一致的。在进行反序列化时,JVM会把传来
的字节流中的serialVersionUID于本地相应实体类的serialVersionUID进行比较。如果相同说明是一致的,可以进
行反序列化,否则会出现反序列化版本一致的异常,即是InvalidCastException。
接下来将序列化与反序列化放在一起
public class SerializeTest {
		public static void main(String[] args) {
			Person person = new Person("jim",20,"哈尔滨");
			savePerson(person);
			Person person2=loadPerson();
			System.out.println(person==person2);
		}
		private static Person loadPerson() {//反序列化
			ObjectInputStream ois=null;
			try {
				ois=new ObjectInputStream(new FileInputStream("D:/person3.dat"));
				return (Person)ois.readObject();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}finally {
				try {
					ois.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return null;
		}
		private static void savePerson(Person person) {//序列化
			ObjectOutputStream oos=null;
			try {
				
				oos=new ObjectOutputStream(new FileOutputStream("D:/person3.dat"));
				oos.writeObject(person);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
}
	在序列化接口中有一个关键字叫做transient,当使用这个关键字修饰需要序列化的对象的属性时候,该属性不再
被序列化,更谈不上被反序列化。
	拓展,程序员可以自定义序列化代码,只要将想要序列化的对象实现Externalizable接口即可,但此时transient
关键字不再起作用,不管有没有用它修饰属性,该属性都会被自定义的序列化方法进行序列化,除非这个序列化
方法中不对这个属性进行序列化。
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;

public class Person implements Externalizable{

	private static final long serialVersionUID = 1L;
		private String name;
		private int age;
		private String address;
		public Person() {
			super();
		}
		public Person(String name, int age, String address) {
			super();
			this.name = name;
			this.age = age;
			this.address = address;
		}
		@Override
		public String toString() {
			return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public String getAddress() {
			return address;
		}
		public void setAddress(String address) {
			this.address = address;
		}
		//重写输入流方法,反序列化过程
		@Override
		public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
			this.setName((String)in.readObject());
			this.setAge(in.readInt());
			
		}
		//重写输出流方法,序列化过程
		@Override
		public void writeExternal(ObjectOutput out) throws IOException {
			out.writeObject(this.getName());
			out.writeObject(this.getAge());
		}
}

本文地址:https://blog.csdn.net/LeCoe/article/details/107584171