Java序列化

Java 序列化

本文所用源码地址

序列化定义

  • 序列化是一种处理对象流的机制。

  • 对象流是将对象的内容流化,可以对流化后的对象进行读写操作,也可以对流化后的对象进行网络传输。

  • 序列化是为了解决在对对象流进行读写操作时可能引发的问题。

实现序列化、反序列化

1、一般通过 实现 serializable 实现

使用一个输出流 (字符流、字节流)来构造一个 ObjectOutputStream 对象流

objectOutputStream.writeObject(student); //序列化

使用一个输出流 (字符流、字节流)来构造一个 ObjectInputStream 对象流

Student student = (Student) objectInputStream.readObject(); // 反序列化

2、 还可以实现 Externalizable 实现

public class Student implements Serializable {
    String name;
    int age;
    String gender;

    public Student() {
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
}
    /**
     * 序列化
     */
    private static void serialize(String path) {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(path);
            oos = new ObjectOutputStream(fos);
            Student student = new Student("lucas", 20, "male");
            System.out.println("序列化 ==> " + student);
            oos.writeObject(student);
            oos.flush();
            oos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 反序列化
     */
    private static void unSerialize(String path) {
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = new FileInputStream(path);
            ois = new ObjectInputStream(fis);
            Student student = (Student) ois.readObject();
            System.out.println("反序列化 ==> " + student);
            ois.close();
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

持久化的作用

Java 允许在内存中创建可复用的对象,但一般情况下,只有 jvm 运行时,这些对象才可能存在,这些对象的生命周期不会比 jvm 的生命周期更长。但在现实应用中,可能要求在 jvm 停止运行之后能够保存持久化的对象,并在将来重新读取被保存的对象。

Java 序列化就能延长持久化对象的生命周期!

序列化特点

1、持久化对象时,会把对象的成员变量保存为一组字节,使用时再将字节组装成对象
2、不会持久化的静态变量
3、不会持久化 transient 修饰的变量
public class Person implements Serializable {

    public static String ATTR = "";
    private String name;
    private transient String age;

    public Person() {
    }
}
  • 序列化和反序列化中间没有修改过静态变量,会读取到 jvm 缓存的值,看起来像是也持久化了静态变量
private static void test2() {
        String path = "person.txt";
        Person person = new Person();
        Person.ATTR = "person";
        person.setName("Joe");
        System.out.println("attr : " + Person.ATTR);
        System.out.println("name : " + person.getName());
        serialize(path, person);
        Person person1 = (Person) unSerialize(path);
        System.out.println("attr : " + Person.ATTR);
        System.out.println("name : " + person1.getName());
    }

  • 序列化和反序列化中间修改过静态变量
private static void test3() {
        String path = "person.txt";
        Person person = new Person();
        person.setName("Joe");
        person.setAge("20");
        Person.ATTR = "person";
        System.out.println("attr : " + Person.ATTR);
        System.out.println("name : " + person.getName());
        System.out.println("age : " + person.getAge());
        serialize(path, person);
        Person.ATTR = "person1";
        Person person1 = (Person) unSerialize(path);
        System.out.println("attr : " + Person.ATTR);
        System.out.println("name : " + person1.getName());
        System.out.println("age : " + person1.getAge());
    }

在这里插入图片描述

拓展

public class User1 implements Externalizable {
    private String username;
    private transient String id;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(id);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        id = (String) in.readObject();
    }
}
private static void test1() throws IOException, ClassNotFoundException {
    User1 user = new User1();
    user.setUsername("yes");
    user.setId("water");
    ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream(new File("user1")));
    objectOutput.writeObject(user);

    ObjectInput objectInput = new ObjectInputStream(new FileInputStream(new File("user1")));
    user = (User1) objectInput.readObject();

    System.out.println(user.getUsername());
    System.out.println(user.getId());

    objectOutput.close();
    objectInput.close();
}

在这里插入图片描述

transient 关键字

1)transient修饰的变量不能被序列化;

2)transient只作用于实现 Serializable 接口;

3)transient只能用来修饰普通成员变量字段;

4)不管有没有 transient 修饰,静态变量都不能被序列化;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当面试中被问到关于Java序列化的问题时,你可以准备以下问题和答案: 问题1:什么是Java序列化? 答:Java序列化是指将Java对象转换为字节流的过程。通过将对象序列化为字节流,我们可以将其持久化保存在文件中或通过网络传输到其他系统。 问题2:为什么要使用Java序列化? 答:Java序列化提供了一种方便的方式来持久化对象数据以及在网络间传输对象。它可以帮助我们保存对象状态并在需要时还原对象。 问题3:如何实现Java序列化? 答:要使一个Java类可序列化,需要满足以下条件: - 类必须实现java.io.Serializable接口。 - 类的所有非瞬态成员变量(即不包含transient关键字修饰的变量)也必须是可序列化的。 问题4:什么是瞬态变量? 答:瞬态变量是指被transient关键字修饰的成员变量。这些变量不会被序列化和反序列化,它们的值在对象反序列化时被设为默认值。 问题5:如何自定义序列化? 答:可以通过实现自定义的writeObject()和readObject()方法来自定义序列化过程。这些方法允许我们在对象序列化和反序列化的过程中控制数据的读写。 问题6:Java序列化中有什么安全问题? 答:Java序列化存在安全隐患,主要是由于它可以导致远程代码执行。攻击者可以通过构造恶意序列化数据来执行未授权的代码。为了解决这个问题,可以使用一些安全机制,如禁用某些类的序列化或使用安全的序列化方案。 这些问题和答案应该能帮助你在面试中回答关于Java序列化的问题。当然,在回答时确保理解问题的背景和提供具体的例子将有助于展示你的知识和理解能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值