当前位置: 移动技术网 > IT编程>开发语言>Java > java学习记录分享(十一)

java学习记录分享(十一)

2020年07月27日  | 移动技术网IT编程  | 我要评论

序列化和反序列化

	序列化就是指把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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网