序列化和反序列化(二)——Serializable 接口

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangshuxuncom/article/details/89496176

Serializable 接口:该接口没有方法或字段,仅用于标识由该接口实现类创建的对象是可序列化的。

       示例:

import java.io.Serializable;

public class UserInfo implements Serializable {

	private static final long serialVersionUID = -564040236692883153L;
	private int age;
	private String name;

	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "name='" + name + '\'' + ", age=" + age;
	}
}
import java.io.*;

public class Test {
	
	/**
	 * 序列化
	 * 
	 * @author GaoHuanjie
	 */
	public static void serialize(){
		UserInfo userInfo = new UserInfo();
		userInfo.setAge(23);
		userInfo.setName("Tom");
		System.out.println(userInfo);
		ObjectOutput objectOutput = null;
		try {
			objectOutput = new ObjectOutputStream(new FileOutputStream("D:\\user_info.ser"));
			objectOutput.writeObject(userInfo);
			objectOutput.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (objectOutput!=null) {
				try {
					objectOutput.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 反序列化
	 * 
	 * @author GaoHuanjie
	 */
	public static void deserialize(){
		ObjectInput objectInput = null;
		try {
			objectInput = new ObjectInputStream(new FileInputStream("D:\\user_info.ser"));
			UserInfo userInfo = (UserInfo) objectInput.readObject();
			System.out.println(userInfo);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (objectInput!=null) {
				try {
					objectInput.close();
				} catch (IOException e) {
					e.printStackTrace();
				} 
			}
		}
	}

	public static void main(String[] args) {
		serialize();//序列化
		deserialize();//反序列化
	}
}

serialVersionUID常量

       实现Serializable接口的类须显式声明serialVersionUID常量,该常量作用如下:反序列化能否成功取决于三方面,首先序列化和反序列化类所在包相同,其次序列化和反序列化类的类名相同,最后序列化和反序列化类serialVersionUID的值要相同,两个类中的代码可以不同,如果不指定serialVersionUID,则类出现警告,但这是次要的,更重要的是序列化时将根据JavaTM)对象序列化规范为该类计算一个默认的serialVersionUID值,这就要求反序列化时使用的类与序列化时使用的类必须完全相同(有相同的属性和方法),否则反序列化失败,因为反序列化时serialVersionUID的值也是根据JavaTM)对象序列化规范计算出来的默认值,由于序列化类代码和反序列化类代码不同,则serialVersionUID的值肯定不同;但在实际开发中序列化类代码和反序列化类代码极有可能不同,在这种情况下为了反序列化成功就要求显式声明serialVersionUID常量且值要相同。serialVersionUID的生成策略有两种:一个是固定的 1L,一个是根据JavaTM)对象序列化规范生成的 long 类型数据;如果没有特殊需求,推荐使用固定值,这样便于序列化类代码和反序列化类serialVersionUID一致;如果限制某些用户的使用,则推荐第二种生成策略。

transient 关键字

       在序列化时,transient 关键字修饰的成员变量不会被序列化;在反序列化时,transient 关键字修饰的成员变量被赋以默认值,如整型为0,浮点型为0.0,引用类型为null

static关键字

       在序列化时,static关键字修饰的成员变量不会被序列化。序列化保存的是对象的状态,静态变量属于类的状态,因此序列化并不保存静态变量,即序列化信息中不包含这个静态成员域。

import java.io.Serializable;

public class UserInfo implements Serializable {

	private static final long serialVersionUID = 1L;
	private static int count;
	public UserInfo() {
		count++;
	}
	public String toString() {
		return "count:" + count;
	}
}

       static修饰的成员变量,序列化和反序列化代码在一个进程中执行时会序列化成功,因为序列化时jvm已经把静态变量加载进来了,所以反序列化时获取的是加载好的静态变量,如下例子:

import java.io.*;

public class Test {

	public static void main(String[] args) {
		try {
			ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("user_info.ser"));
			objectOutput.writeObject(new UserInfo());
			objectOutput.close();

			ObjectInput objectInput = new ObjectInputStream(new FileInputStream("user_info.ser"));
			UserInfo userInfo = (UserInfo) objectInput.readObject();
			System.out.println(userInfo);
			objectInput.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

       static修饰的成员变量,序列化和反序列化代码不再一个进程,由于反序列化时是重新加载静态变量,所以静态变量是初始值,如下列子:

序列化:

import java.io.*;

public class Test1 {

	public static void main(String[] args) {
		try {
			ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("user_info.ser"));
			objectOutput.writeObject(new UserInfo());
			objectOutput.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

反序列化:
import java.io.*;

public class Test2 {

	public static void main(String[] args) {
		try {
			ObjectInput objectInput = new ObjectInputStream(new FileInputStream("user_info.ser"));
			UserInfo userInfo = (UserInfo) objectInput.readObject();
			System.out.println(userInfo);
			objectInput.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

猜你喜欢

转载自blog.csdn.net/wangshuxuncom/article/details/89496176