Java序列化面试

Java序列化

序列化是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

序列化的作用

  • 持久化对象及其状态到内存或者磁盘

Java 平台允许我们在内存中创建可复用的 Java 对象,但一般情况下,只有当 JVM 处于运行时,这些对象才可能存在,即这些对象的生命周期不会比 JVM 的生命周期更长。 但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java 对象序列化可以实现该功能。

  • 序列化用户远程对象传输

除了在持久化对象时会用到对象序列化之外,当使用 RMI(远程方法调用,前段时间的log4j2的漏洞就是通过rmi),或在网络中传递对象时,都会用到对象序列化。 Java序列化API 为处理对象序列化提供了一个标准机制。

Serializable实现序列化

将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,只是为了标注该对象是可被序列化的,然后使用一个输出流(如: FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,然后使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

废话不多说,上个Demo给大家乐呵乐呵。

public class User implements Serializable {

    private static final long serialVersionUID = 1619078257311L;

    private String name;
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
    public static void main(String[] args) throws Exception{
        OutputStream os = new FileOutputStream("/Users/jerry/Desktop/User.txt");
        ObjectOutputStream ops = new ObjectOutputStream(os);
        User user = new User("Jerry",18);
        ops.writeObject(user);
        ops.close();
        System.out.println("开始序列化-----" + user); 

        InputStream is = new FileInputStream("/Users/jerry/Desktop/User.txt");
        ObjectInputStream ips = new ObjectInputStream(is);
        User users = (User)ips.readObject();
        ips.close();
        System.out.println("反序列化------"+users);
    }

}

控制台输出:
在这里插入图片描述
文件内容:
在这里插入图片描述
乱码是因为我们在保存的时候是通过二进制写入进行保存的,所以属于正常现象。

当我们在使用 Java 对象序列化时,会把其状态保存为一组字节,之后再将这些字节组装成对象。需要注意的是,在对象序列化时保存的是对象的”状态”,即它的成员变量。因此对象序列化不会关注类中的静态变量,所以静态变量不会被序列化

序列化ID

细心的人会发现在刚才的User类中有一个serialVersionUID字段,该字段的作用是在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类,当序列化ID不一致时,会抛出InvalidClassException错误。
在这里插入图片描述

transient关键字防止序列化

对于一些敏感的字段,比如密码,当不希望该字段进行序列化时,可以使用transient关键字来防止序列化。

transient private Integer age;

此时的age字段就没有被序列化。
在这里插入图片描述

最后需要注意的一点是当类中有其它类作为字段的时候,如果该引用类没有实现序列化Serializable接口的话,那么在序列化的时候就会抛出NotSerializableException错误。
在这里插入图片描述

好的。

我说完了。

你也看完了。

真棒。

在这里插入图片描述

面试中被问到关于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、付费专栏及课程。

余额充值