目录

Java8新特性

Java 8 你知道有什么新特性?

Java 中 stream 的 API 介绍一下

Stream 流的并行 API 是什么?

序列化

什么是序列化?什么是反序列化?

如果有些字段不想进行序列化怎么办?

常见序列化协议有哪些?

怎么把一个对象从一个jvm转移到另一个jvm?


Java8新特性

Java8的新特性

1. Lambda 表达式(最核心)

  • 核心作用:简化「匿名内部类」的写法,实现函数式编程,让代码更简洁;

 传统匿名内部类(线程创建)
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("传统写法");
    }
}).start();
// Lambda 简化(核心:()->{})
new Thread(() -> System.out.println("Lambda写法")).start();

 集合排序简化
List<String> list = Arrays.asList("b", "a", "c");
// 传统Comparator
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
});
// Lambda简化
Collections.sort(list, (o1, o2) -> o1.compareTo(o2));

2. Stream 流(集合处理效率提升)

核心作用:以声明式方式处理集合(过滤、映射、排序、统计等),替代传统 for 循环,代码更简洁且支持并行处理;

List<User> userList = Arrays.asList(
    new User("张三", 20),
    new User("李四", 30),
    new User("王五", 20)
);

// 1. 筛选年龄=20的用户,提取姓名,转为List(传统for循环需多行)
List<String> nameList = userList.stream()
    .filter(user -> user.getAge() == 20) // 中间操作:过滤
    .map(User::getName) // 中间操作:映射提取姓名
    .collect(Collectors.toList()); // 终止操作:收集结果

// 2. 统计年龄总和
int totalAge = userList.stream()
    .mapToInt(User::getAge)
    .sum();

3. 函数式接口(@FunctionalInterface)

  • 核心定义:只有一个抽象方法的接口(可含默认方法 / 静态方法),是 Lambda 表达式的 “载体”;

// 自定义函数式接口(@FunctionalInterface可选,但推荐加,编译器会校验)
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}

// Lambda实现接口
Calculator add = (a, b) -> a + b;
System.out.println(add.calculate(1, 2)); // 输出3

4. Optional 类(解决空指针)

  • 核心作用:封装可能为 null 的对象,通过链式调用避免 NullPointerException,替代传统的 if (obj != null) 判空;

  • 常用方法ofNullable()(包装可能为 null 的对象)、orElse()(空时返回默认值)、ifPresent()(非空时执行操作);

  • 适用场景:对象属性获取、方法返回值处理(避免层层判空);

import java.util.Optional;
public class OptionalDemo {
    public static void main(String[] args) {
        // 模拟业务场景:user对象可能为null(比如从数据库查询结果为空)
        User user = null; 
        // ==================== 传统判空方式 ====================
        // 问题:多层嵌套判空(易出错,代码冗余
        // 逻辑:先判断user非空,再判断name非空,双重判空避免NullPointerException
        if (user != null && user.getName() != null) {
            System.out.println(user.getName());
        }

        // ==================== Optional简化方式 ====================
        // ofNullable:空安全方法,支持传入null.
         若传入null,则返回空的Optional;若传入非null则返回包含该对象的Optional
        Optional<User> optional = Optional.ofNullable(user);      把User对象放入Optional里面
        
        // 2. 链式调用:空安全提取姓名并消费(非空时执行打印)
        // map(User::getName):若Optional为空,直接返回空Optional,不执行getName();若非空,提取name并包装为Optional<String>
        // ifPresent():仅当Optional<String>非空时,执行括号内的打印逻辑,空则无任何操作(无需手动判空)
        optional.map(User::getName)            链式调用
                .ifPresent(name -> System.out.println(name));     // 非空时执行打印,空则跳过
                                                   
        // 3. 空安全获取姓名,空时返回默认值
        // orElse("默认名称"):若提取的name为空(或user本身为空),返回指定默认值;非空则返回真实name
        String name = optional.map(User::getName).orElse("默认名称");
    }
}

5. 新日期时间 API(java.time 包)

  • 核心问题:替代传统 Date/SimpleDateFormat 的缺陷(线程不安全、API 设计混乱);

  • 核心类

    • LocalDate:仅日期(年 - 月 - 日);

    • LocalTime:仅时间(时 - 分 - 秒);

    • LocalDateTime:日期 + 时间;

    • DateTimeFormatter:线程安全的格式化器(替代 SimpleDateFormat);

// 1. 获取当前日期时间
LocalDateTime now = LocalDateTime.now();
// 2. 格式化(线程安全)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String nowStr = now.format(formatter);
// 3. 日期加减
LocalDateTime tomorrow = now.plusDays(1);
// 4. 解析字符串
LocalDateTime parse = LocalDateTime.parse("2026-01-17 10:00:00", formatter);

Java 8 最常用的新特性有 5 个:① Lambda 表达式,简化匿名内部类;② Stream 流,高效处理集合;③ 函数式接口,支撑 Lambda 编程;④ Optional 类,解决空指针;⑤ 新日期时间 API,替代线程不安全的 Date。核心是函数式编程和集合 / 日期的优化,大幅提升开发效率。

stream流的API

操作类型 作用 常用方法
中间操作 筛选 / 转换数据,返回新 Stream(惰性执行) filter(过滤)、map(映射)、sorted(排序)、distinct(去重)、limit(限制数量)
终止操作 触发 Stream 执行,返回最终结果(非惰性) collect(收集结果)、forEach(遍历)、count(统计数量)、sum/max/min(聚合)、anyMatch/allMatch(匹配判断)
// 模拟业务数据:用户列表
List<User> userList = Arrays.asList(
    new User("张三", 20, "男"),
    new User("李四", 30, "男"),
    new User("王五", 25, "女"),
    new User("赵六", 20, "女")
);

 场景1:筛选+映射(提取20岁用户的姓名)
List<String> nameList = userList.stream()
    .filter(user -> user.getAge() == 20) // 中间操作:筛选年龄=20的用户
    .map(User::getName) // 中间操作:映射提取姓名
    .collect(Collectors.toList()); // 终止操作:收集为List
// 结果:["张三", "赵六"]

 场景2:聚合统计(计算所有用户年龄总和)
int totalAge = userList.stream()
    .mapToInt(User::getAge) // 转为IntStream,支持数值聚合
    .sum(); // 终止操作:求和
// 结果:95

 场景3:分组统计(按性别分组)
Map<String, List<User>> groupByGender = userList.stream()
    .collect(Collectors.groupingBy(User::getGender)); // 按性别分组
// 结果:{男=[张三, 李四], 女=[王五, 赵六]}

 场景4:匹配判断(是否存在30岁用户)
boolean has30Age = userList.stream()
    .anyMatch(user -> user.getAge() == 30); // 终止操作:任意匹配
// 结果:true

 场景5:并行流(大数据量处理,多线程加速)
long count = userList.parallelStream() // 并行流(替代stream())
    .filter(user -> user.getGender().equals("女"))
    .count();
// 结果:2

ParallelStream并行流

并行流(ParallelStream)就是将源数据分为多个子流对象进行多线程操作,然后将处理的结果再汇总为一个流对象,底层是使用通用的 fork/join 池来实现。遵循 “分而治之(Fork/Join)” 思想 —— 将大任务拆分为多个独立小任务并行计算,再合并小任务结果

Stream串行流与并行流的主要区别:

并行流(ParallelStream)是 Stream 的多线程版本,底层用 Fork/Join 池将数据拆分为多个子任务并行处理再汇总;获取方式是 parallelStream () 或 stream ().parallel (),适合大数据量 / 计算密集型场景,但要注意线程安全(避免共享变量)、小数据量用反而慢,且执行顺序不可控。

序列化

序列化与反序列化

序列化Serialization

  • 通俗解释:把内存中的 Java 对象(如 User、Order)转换成字节序列(二进制数据)的过程;

  • 专业定义:将对象的状态信息(属性值)转换为可存储(如文件)或传输(如网络)的字节流的过程。

反序列化(Deserialization)

  • 通俗解释:把序列化生成的字节序列,重新恢复为内存中 Java 对象的过程;

  • 专业定义:将字节流转换回对象的状态信息,重建原对象的过程。

变量不序列化的做法

对于不想进行序列化的变量,使用 transient 关键字修饰。

transient 关键字的作用是:阻止实例中那些用此关键字修饰的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

关于 transient 还有几点注意:

  • transient 只能修饰变量,不能修饰类和方法。

  • transient 修饰的变量,在反序列化后变量值将会被置成类型的默认值。例如,如果是修饰 int 类型,那么反序列后结果就是 0

  • static 变量因为不属于任何对象(Object),所以无论有没有 transient 关键字修饰,均不会被序列化。

常见序列化协议

协议类型 代表 性能 跨语言 可读性 适用场景
原生 Java 序列化 Serializable 简单本地持久化
文本类 JSON/XML 前后端交互、接口调试
二进制类 Protobuf 高性能 RPC、跨语言分布式系统
二进制类 Kryo 极高 Java 专属大数据、缓存场景
  1. 原生 JDK 序列化(基于 Serializable 接口)

    1. 核心原理:通过 ObjectOutputStream/ObjectInputStream 实现对象与字节流的转换,是 Java 自带的序列化方式。

    2. 优点:无需引入第三方依赖,使用简单,与 Java 深度绑定。

    3. 缺点

      • 序列化后的字节流体积大,效率低;

      • 不支持跨语言(只能在 Java 程序间传输);

      • 存在安全漏洞,可能被恶意利用反序列化攻击。

    4. 适用场景:简单 Java 应用的本地持久化(如 Session 存储),不推荐分布式系统使用。

  2. JSON 相关协议

    • 核心代表:Jackson、Gson、Fastjson

    • 原理:将对象转换为键值对结构的 JSON 字符串。

    • 优点:跨语言支持极好,可读性强,调试方便;生态完善,几乎所有编程语言都有解析库。

    • 缺点:序列化后体积较大,性能低于二进制协议;无法直接序列化复杂对象(如带循环引用的对象)。

    • 适用场景:前后端数据交互、接口报文传输、配置文件存储。

  3. Protobuf(Protocol Buffers)

    1. 开发者:Google

    2. 核心原理:基于预定义的 .proto 协议文件生成代码,严格约定数据结构,序列化后体积极小。

    3. 优点:序列化 / 反序列化速度极快,字节体积是 JSON 的 1/3 左右;跨语言支持完善;支持版本向后兼容。

    4. 缺点:需要编写 .proto 文件,有一定学习成本;可读性差(二进制格式)。

    5. 适用场景:高性能 RPC 通信(如 gRPC 框架)、分布式系统间的数据传输、大数据场景。

  4. Kryo

    1. 核心特点:高性能 Java 专属二进制序列化框架,速度远超 JDK 序列化。

    2. 优点:序列化效率极高,体积小;API 简洁,易于使用。

    3. 缺点:不支持跨语言;对类的版本变化敏感,需注意兼容性。

    4. 适用场景:Java 分布式系统的内存数据传输(如 Spark、Hadoop)、缓存存储。

跨语言 + 高性能 → 选 Protobuf

Java 专属 + 极致性能 → 选 Kryo

前后端交互 / 调试 → 选 JSON

传统企业级应用 → 选 XML

将对象从一个jvm转移到另一个jvm

将对象从一个 JVM 转移到另一个 JVM,本质是先把对象转为可传输 / 可存储的格式,再通过网络 / 存储介质传递,最后在目标 JVM 恢复为对象,核心有 4 类方案(按使用频率排序),其中「序列化 + 网络传输」是基础,RPC 是工程化最优解:

方案类型 核心原理 适用场景
序列化 + 网络套接字 手动序列化对象为字节流,Socket 传输 自定义轻量通信、学习 / 测试场景
消息队列(MQ) 序列化对象后封装为消息,MQ 异步传输 分布式系统解耦、异步通信
RPC 框架(gRPC/Dubbo) 封装序列化 + 网络 + 协议,一键远程调用 微服务同步通信、生产环境首选
共享存储(DB/Redis) 序列化对象后存共享介质,目标 JVM 读取 数据共享、非实时传输场景

上述内容也同步在我的飞书,欢迎访问

https://my.feishu.cn/wiki/QLauws6lWif1pnkhB8IcAvkhncc?from=from_copylink

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,你们的支持就是我坚持下去的动力!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐