Java中带继承的对象序列化

作者: Arvin Chen 分类: Java 来源: Break易站(www.breakyizhan.com)

Java中带继承的对象序列化

序列化是一种将对象状态转换为字节流的机制。反序列化是相反的过程,其中字节流用于在内存中重新创建实际的Java对象。

有一些关于继承的序列化情况:

情况1:如果超类是可序列化的,那么子类是可自动序列化的:如果超类是可序列化的,那么默认情况下每个子类都是可序列化的。因此,即使子类没有实现Serializable接口(如果它的超类实现了Serializable),那么我们也可以序列化子类对象。

// Java program to demonstrate 
// that if superclass is
// serializable then subclass 
// is automatically serializable

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

// superclass A 
// implementing Serializable interface
class A implements Serializable
{
	int i;
	
	// parameterized constructor
	public A(int i) 
	{
		this.i = i;
	}
	
}

// subclass B 
// B class doesn't implement Serializable
// interface.
class B extends A
{
	int j;
	
	// parameterized constructor
	public B(int i, int j) 
	{
		super(i);
		this.j = j;
	}
}

// Driver class
public class Test
{
	public static void main(String[] args) 
			throws Exception 
	{
		B b1 = new B(10,20);
		
		System.out.println("i = " + b1.i);
		System.out.println("j = " + b1.j);
		
		/* Serializing B's(subclass) object */
		
		//Saving of object in a file
		FileOutputStream fos = new FileOutputStream("abc.ser");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
			
		// Method for serialization of B's class object
		oos.writeObject(b1);
			
		// closing streams
		oos.close();
		fos.close();
			
		System.out.println("Object has been serialized");
		
		/* De-Serializing B's(subclass) object */
		
		// Reading the object from a file
		FileInputStream fis = new FileInputStream("abc.ser");
		ObjectInputStream ois = new ObjectInputStream(fis);
			
		// Method for de-serialization of B's class object
		B b2 = (B)ois.readObject();
			
		// closing streams
		ois.close();
		fis.close();
			
		System.out.println("Object has been deserialized");
		
		System.out.println("i = " + b2.i);
		System.out.println("j = " + b2.j);
	}
}

输出:

i = 10
j = 20
Object has been serialized
Object has been deserialized
i = 10
j = 20

Java中带继承的对象序列化

如果超类不是可序列化的,那么子类仍然可以被序列化:即使超类没有实现Serializable接口,如果子类本身实现了Serializable接口,我们也可以序列化子类对象。所以我们可以说为了序列化子类对象,超类不需要可序列化。但是在这种情况下,序列化过程中超类的实例会发生什么。以下过程解释了这一点。

 

当一个类是可序列化的,但它的超类不是时会发生什么?

  • 序列化:在序列化时,如果任何实例变量继承自不可序列化的超类,那么JVM将忽略该实例变量的原始值并将缺省值保存到文件中。
  • 反序列化:在反序列化时,如果存在任何不可序列化的超类,那么JVM将在超类中执行实例控制流。为了在类中执行实例控制流,JVM将始终调用该类的默认(无参数)构造函数。所以每个不可序列化的超类必须包含默认的构造函数,否则我们会得到运行时异常。
// Java program to demonstrate 
// the case if superclass need
// not to be serializable 
// while serializing subclass 

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;;

// superclass A 
// A class doesn't implement Serializable
// interface.
class A 
{
	int i;
	
	// parameterized constructor
	public A(int i) 
	{
		this.i = i;
	}
	
	// default constructor
	// this constructor must be present
	// otherwise we will get runtime exception
	public A()
	{
		i = 50;
		System.out.println("A's class constructor called");
	}
	
}

// subclass B 
// implementing Serializable interface
class B extends A implements Serializable
{
	int j;
	
	// parameterized constructor
	public B(int i,int j) 
	{
		super(i);
		this.j = j;
	}
}

// Driver class
public class Test
{
	public static void main(String[] args) 
			throws Exception 
	{
		B b1 = new B(10,20);
		
		System.out.println("i = " + b1.i);
		System.out.println("j = " + b1.j);
		
		// Serializing B's(subclass) object 
		
		//Saving of object in a file
		FileOutputStream fos = new FileOutputStream("abc.ser");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
			
		// Method for serialization of B's class object
		oos.writeObject(b1);
			
		// closing streams
		oos.close();
		fos.close();
			
		System.out.println("Object has been serialized");
		
		// De-Serializing B's(subclass) object 
		
		// Reading the object from a file
		FileInputStream fis = new FileInputStream("abc.ser");
		ObjectInputStream ois = new ObjectInputStream(fis);
			
		// Method for de-serialization of B's class object
		B b2 = (B)ois.readObject();
			
		// closing streams
		ois.close();
		fis.close();
			
		System.out.println("Object has been deserialized");
		
		System.out.println("i = " + b2.i);
		System.out.println("j = " + b2.j);
	}
}

输出:

i = 10
j = 20
Object has been serialized
A's class constructor called
Object has been deserialized
i = 0
j = 20

Java中带继承的对象序列化

如果超类是可序列化的,但我们不希望子类被序列化:没有直接的方法来阻止java中的子类进行序列化。程序员可以通过在子类中实现writeObject()和readObject()方法来实现这一点,并且需要从这些方法中抛出NotSerializableException异常。这些方法分别在序列化和反序列化过程中执行。通过重写这些方法,我们只是实现了我们自己的定制序列化。

// Java program to demonstrate 
// how to prevent 
// subclass from serialization

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

// superclass A 
// implementing Serializable interface
class A implements Serializable
{
	int i;
	
	// parameterized constructor
	public A(int i) 
	{
		this.i = i;
	}
	
}

// subclass B 
// B class doesn't implement Serializable
// interface.
class B extends A
{
	int j;
	
	// parameterized constructor
	public B(int i,int j) 
	{
		super(i);
		this.j = j;
	}
	
	// By implementing writeObject method, 
	// we can prevent
	// subclass from serialization
	private void writeObject(ObjectOutputStream out) throws IOException
	{
		throw new NotSerializableException();
	}
	
	// By implementing readObject method, 
	// we can prevent
	// subclass from de-serialization
	private void readObject(ObjectInputStream in) throws IOException
	{
		throw new NotSerializableException();
	}
	
}

// Driver class
public class Test
{
	public static void main(String[] args) 
			throws Exception 
	{
		B b1 = new B(10, 20);
		
		System.out.println("i = " + b1.i);
		System.out.println("j = " + b1.j);
		
		// Serializing B's(subclass) object 
		
		//Saving of object in a file
		FileOutputStream fos = new FileOutputStream("abc.ser");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
			
		// Method for serialization of B's class object
		oos.writeObject(b1);
			
		// closing streams
		oos.close();
		fos.close();
			
		System.out.println("Object has been serialized");
		
		// De-Serializing B's(subclass) object 
		
		// Reading the object from a file
		FileInputStream fis = new FileInputStream("abc.ser");
		ObjectInputStream ois = new ObjectInputStream(fis);
			
		// Method for de-serialization of B's class object
		B b2 = (B)ois.readObject();
			
		// closing streams
		ois.close();
		fis.close();
			
		System.out.println("Object has been deserialized");
		
		System.out.println("i = " + b2.i);
		System.out.println("j = " + b2.j);
	}
}

输出:

i = 10
j = 20
Exception in thread "main" java.io.NotSerializableException
	at B.writeObject(Test.java:44)
  •   本文标题:Java中带继承的对象序列化 - Break易站
    转载请保留页面地址:https://www.breakyizhan.com/java/4249.html

    发表笔记

    电子邮件地址不会被公开。 必填项已用*标注

    更多阅读