【Java基础 | 第七篇】Java8新特性 和 序列化
目录
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 专属大数据、缓存场景 |
-
原生 JDK 序列化(基于
Serializable接口)-
核心原理:通过
ObjectOutputStream/ObjectInputStream实现对象与字节流的转换,是 Java 自带的序列化方式。 -
优点:无需引入第三方依赖,使用简单,与 Java 深度绑定。
-
缺点:
-
序列化后的字节流体积大,效率低;
-
不支持跨语言(只能在 Java 程序间传输);
-
存在安全漏洞,可能被恶意利用反序列化攻击。
-
-
适用场景:简单 Java 应用的本地持久化(如 Session 存储),不推荐分布式系统使用。
-
-
JSON 相关协议
-
核心代表:Jackson、Gson、Fastjson
-
原理:将对象转换为键值对结构的 JSON 字符串。
-
优点:跨语言支持极好,可读性强,调试方便;生态完善,几乎所有编程语言都有解析库。
-
缺点:序列化后体积较大,性能低于二进制协议;无法直接序列化复杂对象(如带循环引用的对象)。
-
适用场景:前后端数据交互、接口报文传输、配置文件存储。
-
-
Protobuf(Protocol Buffers)
-
开发者:Google
-
核心原理:基于预定义的
.proto协议文件生成代码,严格约定数据结构,序列化后体积极小。 -
优点:序列化 / 反序列化速度极快,字节体积是 JSON 的 1/3 左右;跨语言支持完善;支持版本向后兼容。
-
缺点:需要编写
.proto文件,有一定学习成本;可读性差(二进制格式)。 -
适用场景:高性能 RPC 通信(如 gRPC 框架)、分布式系统间的数据传输、大数据场景。
-
-
Kryo
-
核心特点:高性能 Java 专属二进制序列化框架,速度远超 JDK 序列化。
-
优点:序列化效率极高,体积小;API 简洁,易于使用。
-
缺点:不支持跨语言;对类的版本变化敏感,需注意兼容性。
-
适用场景: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
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,你们的支持就是我坚持下去的动力!
更多推荐




所有评论(0)