【java IO】转换流 + 对象流 + 序列化详解

Java IO 从入门到深入(第五篇):转换流 + 对象流 + 序列化详解(面试高频)

在前几篇中,我们已经掌握了:

  • File 类
  • 字节流
  • 字符流
  • 缓冲流

但还有两个非常关键的问题:


问题1:字符编码如何真正控制?

我们之前提到:

id="v1y2b3" 复制代码
FileReader 无法指定编码

那如何解决?

👉 转换流


问题2:如何把对象写入文件?

例如:

id="x9z8y7" 复制代码
User 对象 → 保存到磁盘

👉 对象流 + 序列化


本篇重点:

  1. 转换流原理与使用
  2. InputStreamReader / OutputStreamWriter
  3. 对象流 ObjectInputStream / ObjectOutputStream
  4. Serializable 接口
  5. transient 关键字
  6. serialVersionUID(重点)
  7. 常见易错点
  8. 面试高频问题

一、什么是转换流?

转换流的核心作用:

在字节流和字符流之间进行转换

结构:

id="k2m3n4" 复制代码
字节流 ←→ 转换流 ←→ 字符流

二、为什么需要转换流?

问题:

id="a1s2d3" 复制代码
字节流不处理编码
字符流无法指定编码

解决:

id="q4w5e6" 复制代码
转换流 = 手动指定编码

三、InputStreamReader(重点)

作用:

将字节流 → 转换为字符流


使用示例

java 复制代码
import java.io.*;

public class Main {

    public static void main(String[] args) throws Exception {

        InputStreamReader reader =
                new InputStreamReader(
                        new FileInputStream("test.txt"),
                        "UTF-8"
                );

        int data;

        while((data = reader.read()) != -1){
            System.out.print((char)data);
        }

        reader.close();
    }
}

本质

id="m7n8b9" 复制代码
字节 → 解码 → 字符

四、OutputStreamWriter

作用:

字符 → 转换为字节流写出


示例

java 复制代码
OutputStreamWriter writer =
        new OutputStreamWriter(
                new FileOutputStream("test.txt"),
                "UTF-8"
        );

writer.write("你好,Java IO");

writer.close();

五、最佳实践(推荐写法)

java 复制代码
try(
    BufferedReader br =
        new BufferedReader(
            new InputStreamReader(
                new FileInputStream("test.txt"), "UTF-8"
            )
        )
){
    String line;

    while((line = br.readLine()) != null){
        System.out.println(line);
    }
}

👉 这是:

id="z9x8c7" 复制代码
企业级标准写法

六、什么是对象流?

对象流的作用:

将 Java 对象写入文件 / 从文件读取对象


核心类

id="q1w2e3" 复制代码
ObjectOutputStream
ObjectInputStream

七、对象序列化

概念:

id="l1k2j3" 复制代码
对象 → 字节流

八、Serializable 接口

要实现序列化,必须:

java 复制代码
class User implements Serializable

示例

java 复制代码
import java.io.*;

class User implements Serializable {
    String name;
    int age;

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

public class Main {

    public static void main(String[] args) throws Exception {

        ObjectOutputStream oos =
            new ObjectOutputStream(
                new FileOutputStream("user.dat")
            );

        User user = new User("Tom",18);

        oos.writeObject(user);

        oos.close();
    }
}

九、反序列化

java 复制代码
ObjectInputStream ois =
    new ObjectInputStream(
        new FileInputStream("user.dat")
    );

User user = (User) ois.readObject();

System.out.println(user.name);

ois.close();

十、transient 关键字

作用:

不参与序列化


示例

java 复制代码
class User implements Serializable {

    String name;

    transient String password;

}

结果:

id="x5c6v7" 复制代码
password 不会被保存

十一、serialVersionUID(重点)

作用:

控制序列化版本


示例

java 复制代码
class User implements Serializable {

    private static final long serialVersionUID = 1L;

}

为什么需要?

问题:

id="b2n3m4" 复制代码
类结构发生变化

例如:

id="k9l8j7" 复制代码
新增字段
删除字段

如果没有 UID:

id="p0o9i8" 复制代码
反序列化失败

异常:

id="y7t6r5" 复制代码
InvalidClassException

十二、序列化本质(面试重点)

id="f1g2h3" 复制代码
对象 → 字节数组 → 文件

反序列化:

id="u7y6t5" 复制代码
文件 → 字节 → 对象

十三、使用场景

1 数据持久化

id="j1k2l3" 复制代码
对象保存到磁盘

2 网络传输

id="r4t5y6" 复制代码
对象通过 socket 传输

3 缓存系统

id="u8i9o0" 复制代码
对象序列化存储

十四、常见易错点

1 没有实现 Serializable

id="e1r2t3" 复制代码
NotSerializableException

2 忘记 serialVersionUID

id="y1u2i3" 复制代码
版本不兼容

3 静态变量不会被序列化

id="o1p2a3" 复制代码
static 不属于对象

4 transient 字段丢失

id="s4d5f6" 复制代码
反序列化后为默认值

十五、面试高频问题(重点)

1 什么是序列化?

id="g7h8j9" 复制代码
对象 → 字节流

2 为什么需要序列化?

id="k1l2z3" 复制代码
存储
传输

3 transient 作用?

id="x1c2v3" 复制代码
不序列化字段

4 serialVersionUID 有什么用?

id="b1n2m3" 复制代码
版本控制
防止反序列化失败

5 为什么不推荐 Java 原生序列化?

原因:

id="q2w3e4" 复制代码
性能低
不安全
不可读
跨语言差

十六、总结

本篇是 Java IO 的 进阶核心内容


转换流

id="z1x1c1" 复制代码
InputStreamReader
OutputStreamWriter

作用:

id="v2b2n2" 复制代码
控制编码
解决乱码

对象流

id="m3n3b3" 复制代码
ObjectInputStream
ObjectOutputStream

作用:

id="k4l4j4" 复制代码
对象读写

序列化核心

id="h5g5f5" 复制代码
Serializable
transient
serialVersionUID
相关推荐
一棵树73511 小时前
Springboot项目常用工具对比总结
java·spring boot·后端
沈阳信息学奥赛培训1 小时前
#define 和 typedef 的区别
开发语言·c++
Laurence1 小时前
CMake 查找、打印 Qt 所有 Components / 模块列表
开发语言·qt·cmake·打印·查找·所有组件·所有模块
j_xxx404_1 小时前
LeetCode模拟算法精解I:替换问号,提莫攻击与Z字形变换
开发语言·数据结构·c++·算法·leetcode
IT痴者1 小时前
Kotlin 开发注意事项(Android Java 开发者转型指南)
android·java·kotlin
wuqingshun3141591 小时前
产生死锁的四个必要条件
java·jvm
青槿吖1 小时前
第二篇:Spring MVC进阶:注解、返回值与参数接收的花式玩法
java·开发语言·后端·mysql·spring·mvc·mybatis
共享家95272 小时前
Java入门(抽象类 与 接口)
java·开发语言
hanbr2 小时前
C++ string类模拟实现(完整版,含全运算符重载)
java·开发语言