Java序列化继承

Java中具有继承的对象序列化

在序列化中,当引入继承时,则根据超类和子类定义了某些情况,这使对每种情况下的序列化的理解变得更加简单。应遵循的基本规则如下。

1.当超类实现时,可序列化接口而子类则不。

在这种情况下,即使子类未实现Serializable接口,默认情况下,当超类被序列化时,子类的对象也将被序列化。

2.当超类未实现可序列化的接口而子类实现时。

在这种情况下,在子类中继承的超类实例变量不会被序列化,并且在子类的序列化过程中也不会释放其分配的值。此外,在子类序列化期间的JVM也将默认的初始化值重新分配给这些超类的实例变量。
在此场景中需要注意的一点是,超类必须具有默认的无参数构造函数,因为反序列化期间JVM访问超类。如果不存在该构造函数,则会遇到编译时异常。

3.当需要序列化超类而不是子类时(自定义序列化)。

为了防止子类被序列化,我们需要实现writeObject()并readObject()在序列化和反序列化期间由JVM执行的方法以及这些方法抛出NotSerializableException。
我们还可以在这些方法中提供自定义逻辑,这些逻辑将在序列化/去角质素。



序列化继承

相关注意事项
a)序列化时,只对对象的状态进行保存,而不管对象的方法;
b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;但是该对象也要实现序列化接口
d)并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如:

  1. 安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
  2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。
  3. 这些字段用transient修饰,就不被序列化

当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口

import lombok.Data;
import lombok.ToString;

import java.io.*;

public class SerializeTest {
    
    
    public static void main(String[] args) {
    
    
        PageForm pf = new PageForm();
        pf.setPageNum(1);
        pf.setPageSize(10);
        pf.setUserId("l23");

        try {
    
    
            FileOutputStream fos = new FileOutputStream("e:/serialize.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(pf);
            oos.close();
            System.out.println("序列化: " + pf);//序列化: PageForm(super=BaseForm(userId=l23), pageNum=1, pageSize=10)

            FileInputStream fis = new FileInputStream("e:/serialize.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            PageForm form = (PageForm)ois.readObject();
            System.out.println("反序列化: " + form);//反序列化: PageForm(super=BaseForm(userId=l23), pageNum=1, pageSize=10)
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }
}

//父类实现序列化接口,子类自动序列化
@Data
class BaseForm implements Serializable {
    
    
    private transient String  userId;
}

@Data
@ToString(callSuper = true)
class PageForm extends BaseForm {
    
    
    private Integer pageNum;
    private Integer pageSize;
}

序列化结果
在这里插入图片描述

当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化

但是该对象也要实现序列化接口

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.*;

public class SerializeTest2 {
    
    
    public static void main(String[] args) {
    
    
        User user = new User("lipo", new Address("浙江省", "hangzhou"));

        try {
    
    
            FileOutputStream fos = new FileOutputStream("e:/serialize.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(user);
            oos.close();
            System.out.println("序列化: " + user);//序列化: User(username=lipo, address=Address(province=浙江省, city=hangzhou))

            FileInputStream fis = new FileInputStream("e:/serialize.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            User form = (User)ois.readObject();
            ois.close();
            System.out.println("反序列化: " + form);//反序列化: User(username=lipo, address=Address(province=浙江省, city=hangzhou))
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class User implements Serializable {
    
    
    private String username;
    private Address address;//类字段也必须实现序列化接口
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Address implements Serializable {
    
    
    private String province;
    private String city;
}

父类未实现Serializable,子类实现了,序列化子类实例的时候,父类的属性不保存

import lombok.Data;
import lombok.ToString;

import java.io.*;

public class SerializeTest3 {
    
    
    public static void main(String[] args) {
    
    
        Child pf = new Child();
        pf.setPageNum(1);
        pf.setPageSize(10);
        pf.setUserId("l23");

        try {
    
    
            FileOutputStream fos = new FileOutputStream("e:/serialize.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(pf);
            oos.close();
            System.out.println("序列化: " + pf);//序列化: Child(super=Parent(userId=l23), pageNum=1, pageSize=10)

            FileInputStream fis = new FileInputStream("e:/serialize.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Child form = (Child)ois.readObject();
            System.out.println("反序列化: " + form);//反序列化: Child(super=Parent(userId=null), pageNum=1, pageSize=10)
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }
}


@Data
class Parent{
    
    
    private String userId;
}

//父类没有实现序列化,子类实现序列化,子类序列化时,父类属性值丢失
@Data
@ToString(callSuper = true)
class Child extends Parent implements Serializable {
    
    
    private Integer pageNum;
    private Integer pageSize;
}

transient关键字修饰的属性不序列化

import lombok.Data;
import lombok.ToString;

import java.io.*;

public class SerializeTest {
    
    
    public static void main(String[] args) {
    
    
        PageForm pf = new PageForm();
        pf.setPageNum(1);
        pf.setPageSize(10);
        pf.setUserId("l23");

        try {
    
    
            FileOutputStream fos = new FileOutputStream("e:/serialize.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(pf);
            oos.close();
            System.out.println("序列化: " + pf);//序列化: PageForm(super=BaseForm(userId=l23), pageNum=1, pageSize=10)

            FileInputStream fis = new FileInputStream("e:/serialize.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            PageForm form = (PageForm)ois.readObject();
            System.out.println("反序列化: " + form);//反序列化: PageForm(super=BaseForm(userId=l23), pageNum=1, pageSize=null)
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }
}

//父类实现序列化接口,子类自动序列化
@Data
class BaseForm implements Serializable {
    
    
    private String  userId;
}

@Data
@ToString(callSuper = true)
class PageForm extends BaseForm {
    
    
    private Integer pageNum;
    private transient Integer pageSize;
}

猜你喜欢

转载自blog.csdn.net/qq_43842093/article/details/131023843
今日推荐