当前位置: 首页 > news >正文

Java 8 Optional 类实战:从根源杜绝空指针异常的优雅方案

在 Java 开发中,NullPointerException(空指针异常)是最常见的运行时异常之一 —— 据统计,约 30% 的线上故障与空指针相关。传统的 “if-null 判断” 虽然能规避空指针,但会导致代码嵌套层级过深(被戏称为 “if-else 地狱”),可读性与可维护性大幅下降。Java 8 引入的Optional类,通过 “容器化封装” 与 “链式调用”,从语法层面提供了空值处理的优雅方案,彻底改变了空值判断的代码风格。本文将从空指针的痛点出发,详解 Optional 的核心原理、常用方法、避坑指南及业务场景落地,帮你真正掌握 “无空指针” 的编码技巧。​

一、为什么需要 Optional?—— 空指针的痛点与传统方案的局限​

在理解 Optional 之前,我们首先要明确:空指针异常的本质是 “对 null 对象调用方法或访问属性”。例如,当user.getAddress().getCity()中的user或address为 null 时,就会抛出NullPointerException。传统的解决方案是添加层层 if 判断,但这种方式存在诸多问题。​

1.1 传统空值判断的 3 大痛点​

痛点 1:代码嵌套过深,可读性差​

为了避免空指针,需要对每个可能为 null 的对象添加 if 判断,导致代码嵌套层级急剧增加。例如,要获取 “用户的订单的商品的分类名称”,传统代码如下:​

java取消自动换行复制

// 传统空值判断:4层嵌套,可读性差​

public String getProductCategoryName(User user) {​

if (user != null) { // 判断用户是否为null​

List<Order> orders = user.getOrders();​

if (orders != null && !orders.isEmpty()) { // 判断订单列表是否为null且非空​

Order order = orders.get(0);​

if (order != null) { // 判断订单是否为null​

Product product = order.getProduct();​

if (product != null) { // 判断商品是否为null​

Category category = product.getCategory();​

if (category != null) { // 判断分类是否为null​

return category.getName();​

}​

}​

}​

}​

}​

return "默认分类"; // 所有环节都为null时返回默认值​

}​

这段代码中,核心逻辑 “获取分类名称” 被 5 层 if 判断包裹,代码冗长且难以快速定位核心业务逻辑,维护时极易遗漏某个 null 判断。​

痛点 2:代码冗余,重复判断​

在多个地方需要获取同一类对象的属性时,会出现大量重复的 null 判断代码。例如,在订单详情页和用户中心都需要获取 “用户的收货地址城市”,就需要重复编写 “判断 user 是否为 null→判断 address 是否为 null” 的逻辑,导致代码冗余。​

痛点 3:null 的语义不明确​

null本身没有明确的语义 —— 它既可能表示 “对象不存在”(如未查询到用户),也可能表示 “对象存在但属性未设置”(如用户存在但未填写地址)。这种语义模糊会导致后续逻辑难以判断空值的真实原因,增加调试难度。​

1.2 Optional 的核心价值​

Optional 类通过 “将可能为 null 的对象封装为 Optional 容器”,从根本上解决了传统方案的痛点,其核心价值可概括为 3 点:​

  1. 消除嵌套判断:通过链式调用替代层层 if 嵌套,核心逻辑一目了然;​
  1. 强制空值处理:Optional 的方法设计强制开发者处理空值场景(如指定默认值、抛出异常),避免遗漏判断;​
  1. 明确语义:Optional 容器本身就表示 “对象可能存在也可能不存在”,语义清晰,无需额外注释说明。​

用 Optional 重写上述 “获取商品分类名称” 的逻辑,代码会变得异常简洁:​

jav取消自动换行复制

// Optional方案:链式调用,无嵌套判断​

public String getProductCategoryName(User user) {​

return Optional.ofNullable(user) // 封装可能为null的user​

.map(User::getOrders) // 提取订单列表,若user为null则跳过​

.filter(orders -> !orders.isEmpty()) // 过滤空订单列表​

.map(orders -> orders.get(0)) // 提取第一个订单​

.map(Order::getProduct) // 提取商品​

.map(Product::getCategory) // 提取分类​

.map(Category::getName) // 提取分类名称​

.orElse("默认分类"); // 所有环节为null时返回默认值​

}​

这段代码中,核心逻辑通过map()、filter()等方法链式调用,无任何嵌套 if 判断,代码可读性与维护性大幅提升,且强制处理了空值场景(orElse()指定默认值)。​

二、Optional 的核心原理:容器化封装与惰性执行​

要真正掌握 Optional,必须理解其 “容器化封装” 和 “惰性执行” 的底层原理,这是 Optional 区别于传统空值判断的关键。​

2.1 Optional 的本质:可能为 null 的对象容器​

Optional 类本质是一个 “容器”,它包含两种状态:​

  • 存在值(Present):容器中封装了非 null 的对象;​
  • 空值(Empty):容器中没有对象(对应传统的 null,但本身不是 null)。​

Optional 类的构造方法被设计为私有,无法直接通过new Optional()创建实例,只能通过以下 3 个静态方法创建:​

  1. Optional.of(T value):创建包含非 null 值的 Optional 容器,若 value 为 null 则抛出NullPointerException;​
  1. Optional.ofNullable(T value):创建可能包含 null 值的 Optional 容器,若 value 为 null 则返回 Empty 状态的 Optional;​
  1. Optional.empty():创建空值状态的 Optional 容器(等价于Optional.ofNullable(null))。​

示例:创建 Optional 容器​

ja取消自动换行复制

Optional<User> emptyOptional = Optional.empty(); // 等价于Optional.ofNullable(null)​

// 判断Optional的状态​

System.out.println("userOptional1是否存在值:" + userOptional1.isPresent()); // true​

System.out.println("userOptional2是否存在值:" + userOptional2.isPresent()); // false​

System.out.println("emptyOptional是否为空:" + emptyOptional.isEmpty()); // true(Java 11+新增方法)​

}​

// 用户实体类​

static class User {​

private String name;​

private int age;​

public User(String name, int age) {​

this.name = name;​

this.age = age;​

}​

// getter/setter​

public String getName() { return name; }​

public void setName(String name) { this.name = name; }​

public int getAge() { return age; }​

public void setAge(int age) { this.age = age; }​

}​

}​

2.2 惰性执行:中间操作不触发计算​

Optional 的map()、filter()等方法属于 “中间操作”,它们具有 “惰性执行” 的特性 —— 即仅记录操作逻辑,不立即执行,直到调用orElse()、get()等 “终止操作” 时才触发整个链式流程的计算。​

示例:惰性执行特性验证​

j取消自动换行复制

执行结果​

plaintext取消自动换行复制

最终姓名:默认姓名​

从结果可见,由于user为 null,map()和filter()中的打印语句并未执行 —— 这就是惰性执行的体现。只有当调用orElse()时,Optional 才会从左到右遍历链式操作,若某个环节返回 Empty,则后续操作全部跳过,直接返回默认值。​

三、Optional 的核心方法:从创建到结果处理的全流程​

Optional 提供了丰富的方法用于空值处理,按功能可分为 “创建方法”“中间操作方法”“终止操作方法” 三类。掌握这些方法的使用场景,是灵活运用 Optional 的基础。​

3.1 1. 创建方法(3 个核心)​

方法​

作用​

适用场景​

注意事项​

Optional.of(T value)​

创建非 null 值的 Optional​

明确知道 value 非 null(如新建对象)​

value 为 null 时抛出NullPointerException​

Optional.ofNullable(T value)​

创建可能为 null 的 Optional​

不确定 value 是否为 null(如数据库查询结果)​

推荐优先使用,兼容性最强​

Optional.empty()​

创建空值 Optional​

明确返回空值(如方法无结果时)​

等价于Optional.ofNullable(null),但语义更清晰​

3.2 2. 中间操作方法(4 个常用)​

中间操作方法返回新的 Optional,支持链式调用,且具有惰性执行特性。​

(1)map(Function<? super T, ? extends U> mapper):提取对象属性​

  • 作用:若 Optional 为 Present 状态,将容器中的对象通过 mapper 函数转换为另一种类型,返回新的 Optional;若为 Empty 状态,直接返回 Empty。​
  • 场景:提取对象的属性(如从 User 提取 name、从 Order 提取 Product)。​

示例:提取用户的订单列表​

java取消自动换行复制

Optional<User> userOptional = Optional.ofNullable(getUserById(1L));​

// 提取用户的订单列表,若user为null则返回Empty​

Optional<List<Order>> ordersOptional = userOptional.map(User::getOrders);​

(2)flatMap(Function<? super T, Optional<U>> mapper):提取嵌套 Optional 属性​

  • 作用:若 Optional 为 Present 状态,mapper 函数返回的是 Optional,flatMap 会 “展开” 这个嵌套的 Optional,返回 U 类型的 Optional;若为 Empty 状态,直接返回 Empty。​
  • 场景:当提取的属性本身就是 Optional 类型时(如方法返回 Optional),避免出现 Optional<Optional> 的嵌套。​

示例:提取用户的地址(地址方法返回 Optional)​

java取消自动换行复制

// 假设User的getAddress()方法返回Optional<Address>​

Optional<User> userOptional = Optional.ofNullable(getUserById(1L));​

// 用flatMap展开嵌套的Optional,避免Optional<Optional<Address>>​

Optional<Address> addressOptional = userOptional.flatMap(User::getAddress);​

// 若用map,会得到Optional<Optional<Address>>,需额外处理​

Optional<Optional<Address>> nestedAddressOptional = userOptional.map(User::getAddress);​

(3)filter(Predicate<? super T> predicate):过滤符合条件的对象​

  • 作用:若 Optional 为 Present 状态且对象满足 predicate 条件,返回原 Optional;若不满足条件或为 Empty 状态,返回 Empty。​
  • 场景:筛选符合业务条件的对象(如过滤成年用户、非空订单列表)。​

示例:过滤成年用户​

java取消自动换行复制

Optional<User> userOptional = Optional.ofNullable(getUserById(1L));​

// 筛选年龄≥18的用户,若用户为null或年龄<18,返回Empty​

Optional<User> adultUserOptional = userOptional.filter(user -> user.getAge() >= 18);​

(4)ifPresent(Consumer<? super T> action):消费存在的对象​

  • 作用:若 Optional 为 Present 状态,执行 action 消费对象;若为 Empty 状态,不执行任何操作。​
  • 场景:当对象存在时执行某些副作用操作(如打印日志、更新缓存),且无需返回值。​

示例:用户存在时打印日志​

java取消自动换行复制

Optional<User> userOptional = Optional.ofNullable(getUserById(1L));​

// 若用户存在,打印用户信息;若不存在,不执行​

userOptional.ifPresent(user -> System.out.printf("用户存在:%s,年龄:%d%n", user.getName(), user.getAge()));​

3.3 3. 终止操作方法(5 个核心)​

终止操作方法触发链式流程的计算,返回非 Optional 类型的结果(或抛出异常),且 Optional 对象不可再重复使用。​

(1)orElse(T other):空值时返回默认值​

  • 作用:若 Optional 为 Present 状态,返回容器中的对象;若为 Empty 状态,返回指定的默认值 other。​
  • 注意事项:无论 Optional 是否为 Present 状态,other 都会被提前创建(若 other 是新建对象,会产生不必要的开销)。​

示例:获取用户名,空值时返回默认值​

java取消自动换行复制

Optional<User> userOptional = Optional.ofNullable(getUserById(1L));​

// 若用户存在,返回用户名;若不存在,返回"未知用户"​

String userName = userOptional.map(User::getName).orElse("未知用户");​

(2)orElseGet(Supplier<? extends T> supplier):空值时通过 Supplier 生成默认值​

  • 作用:若 Optional 为 Present 状态,返回容器中的对象;若为 Empty 状态,调用 supplier 生成默认值并返回。​
  • 优势:supplier 是惰性执行的,只有当 Optional 为 Empty 时才会调用,避免不必要的对象创建(推荐优先使用,性能更优)。​

示例:空值时生成默认用户(惰性创建)​

java取消自动换行复制

Optional<User> userOptional = Optional.ofNullable(getUserById(1L));​

// 若用户不存在,通过Supplier创建默认用户(仅在空值时执行)​

User defaultUser = userOptional.orElseGet(() -> new User("默认用户", 0));​

(3)orElseThrow(Supplier<? extends X> exceptionSupplier):空值时抛出指定异常​

  • 作用:若 Optional 为 Present 状态,返回容器中的对象;若为 Empty 状态,调用 exceptionSupplier 生成异常并抛出。​
  • 场景:空值属于业务异常场景(如 “用户不存在” 需抛出UserNotFoundException),而非返回默认值。​

示例:用户不存在时抛出异常​

java取消自动换行复制

(4)get():直接获取对象(不推荐)​

  • 作用:若 Optional 为 Present 状态,返回容器中的对象;若为 Empty 状态,抛出NoSuchElementException。​
  • 风险:使用get()前必须确保 Optional 为 Present 状态(需配合isPresent()判断),否则会抛出异常,本质上与传统的 null 判断无区别,不推荐直接使用。​

反例:直接使用 get ()(风险高)​

java取消自动换行复制

正确用法:配合 isPresent () 判断(不推荐,不如用 orElseThrow)​

java取消自动换行复制

(5)ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction):存在时消费,空值时执行备选逻辑​

  • 作用:Java 9 + 新增方法,若 Optional 为 Present 状态,执行 action 消费对象;若为 Empty 状态,执行 emptyAction 备选逻辑。​
  • 场景:需要同时处理 “对象存在” 和 “对象不存在” 两种场景,且无需返回值。​

示例:用户存在时更新缓存,不存在时记录日志​

java取消自动换行复制

Optional<User> userOptional = Optional.ofNullable(getUserById(1L));​

// 存在时更新缓存,不存在时记录日志​

userOptional.ifPresentOrElse(​

user -> cacheService.updateUserCache(user), // 存在时执行​

() -> logger.warn("用户ID=1不存在,未更新缓存") // 空值时执行​

);​

四、Optional 的实战场景:从业务需求到代码落地​

Optional 在实际开发中应用广泛,本节将结合 4 个典型业务场景(用户信息查询、订单数据处理、DTO 转换、集合操作),展示从需求分析到 Optional 代码实现的完整过程。​

4.1 场景 1:用户信息查询与默认值处理​

需求:根据用户 ID 查询用户信息,若用户存在,返回用户的 “姓名 - 年龄” 拼接字符串;若用户不存在或姓名为 null,返回 “未知用户 - 0 岁”。​

传统方案(嵌套 if)​

java取消自动换行复制

public String getUserInfo(Long userId) {​

User user = userDao.getUserById(userId);​

if (user != null) {​

String name = user.getName();​

if (name != null && !name.isEmpty()) {​

return name + "-" + user.getAge() + "岁";​

} else {​

return "未知用户-" + user.getAge() + "岁";​

}​

} else {​

return "未知用户-0岁";​

}​

}​

Optional 方案(链式调用)​

java取消自动换行复制

优化:提取姓名处理逻辑(更简洁)​

java取消自动换行复制

4.2 场景 2:订单数据处理与异常抛出​

需求:根据订单 ID 查询订单详情,若订单不存在,抛出OrderNotFoundException;若订单存在但未支付(状态为UNPAID),抛出OrderUnpaidException;若订单存在且已支付,返回订单的支付金额。​

传统方案(多层 if-else)​

java取消自动换行复制

Optional 方案(链式调用 + 异常抛出)​

java取消自动换行复制

代码解析:​

  1. Optional.ofNullable(order):封装可能为 null 的订单;​
  1. orElseThrow():订单为 null 时抛出 “订单不存在” 异常;​
  1. filter():过滤掉未支付的订单,若订单未支付则返回 Empty;​
  1. 第二个orElseThrow():订单未支付时抛出 “订单未支付” 异常;​
  1. getAmount():此时订单一定存在且已支付,安全获取金额(无需额外判断)。​

4.3 场景 3:DTO 与实体类转换(处理嵌套 null)​

需求:将Order实体类转换为OrderDTO,其中Order包含Product属性,Product包含Category属性。转换规则:​

  • 若Order为 null,返回 null;​
  • 若Product为 null,OrderDTO的productName设为 “未知商品”;​
  • 若Category为 null,OrderDTO的categoryName设为 “未知分类”。​

传统方案(多层 null 判断)​

java取消自动换行复制

Optional 方案(链式调用 + 嵌套处理)​

java取消自动换行复制

代码解析:​

  • 用Optional.ofNullable(order)处理订单 null 的情况;​
  • 提取buildOrderDTO()方法,专注于非 null 订单的转换逻辑;​
  • 用Optional分别处理productName和categoryName的 null 值,避免嵌套 if 判断;​
  • 处理category时,由于product可能为 null,用flatMap()展开嵌套的Optional<Category>。​

4.4 场景 4:集合中的 Optional 处理​

需求:从用户列表中筛选出成年用户(年龄≥18),提取他们的邮箱地址,若邮箱为 null 或为空,排除该用户,最终返回非空邮箱列表。​

传统方案(循环 + if 判断)​

java取消自动换行复制

public List<String> getAdultUserEmails(List<User> userList) {​

List<String> emails = new ArrayList<>();​

if (userList == null || userList.isEmpty()) {​

return emails;​

}​

for (User user : userList) {​

if (user != null && user.getAge() >= 18) {​

String email = user.getEmail();​

if (email != null && !email.isEmpty()) {​

emails.add(email);​

}​

}​

}​

return emails;​

}​

Optional+Stream 方案(链式调用)​

java取消自动换行复制

代码解析:​

  • Optional.ofNullable(userList).stream():处理 List 为 null 的情况,返回空 Stream;​
  • flatMap():将Optional<String>(邮箱)转换为 Stream,若邮箱为 null 或空,返回空 Stream,避免收集到 null 值;​
  • 整个流程无任何显式 if 判断,通过 Stream 和 Optional 的结合,代码更简洁且安全。​

五、Optional 的常见误区与避坑指南​

虽然 Optional 能优雅处理空值,但在使用不当的情况下,仍可能导致代码冗余、性能问题甚至空指针异常。以下是 6 个常见误区及避坑建议:​

5.1 误区 1:用 Optional 封装 null 对象(无意义)​

错误示例:​

java取消自动换行复制

// 错误:将null封装为Optional,再用ofNullable判断,完全多余​

Optional<User> userOptional = Optional.ofNullable(null);​

if (userOptional.isPresent()) {​

// 永远不会执行​

}​

避坑建议:​

  • 若明确对象为 null,直接使用Optional.empty()创建空容器,或直接返回默认值,无需额外封装;​
  • Optional 的核心价值是处理 “可能为 null 的对象”,而非 “明确为 null 的对象”。​

5.2 误区 2:过度使用 Optional(如方法返回 Optional <基本类型>)​

错误示例:​

java取消自动换行复制

// 错误:返回Optional<int>,基本类型的Optional无意义(Java 8无基本类型Optional,需装箱为Integer)​

public Optional<Integer> getUserId(User user) {​

return Optional.ofNullable(user).map(User::getId);​

}​

避坑建议:​

  • 基本类型(int、long、double)建议使用 Java 8 提供的OptionalInt、OptionalLong、OptionalDouble,避免自动装箱的性能开销;​
  • 若方法返回值是 “必须存在的基本类型”(如用户 ID 一定存在),不建议返回 Optional,直接返回基本类型即可。​

正确示例:​

java取消自动换行复制

// 正确:使用OptionalInt处理基本类型​

public OptionalInt getUserId(User user) {​

return Optional.ofNullable(user)​

.mapToInt(User::getId) // 转换为IntStream​

.findFirst(); // 返回OptionalInt​

}​

5.3 误区 3:用 Optional 替代集合的空判断​

错误示例:​

java取消自动换行复制

// 错误:用Optional封装List,判断是否为空,不如直接判断List​

public List<User> getAdultUsers(List<User> userList) {​

return Optional.ofNullable(userList)​

.orElse(new ArrayList<>())​

.stream()​

.filter(user -> user.getAge() >= 18)​

.collect(Collectors.toList());​

}​

避坑建议:​

  • 集合(List、Map、Set)的空判断建议直接使用CollectionUtils.isEmpty()(Apache Commons 工具类)或list == null || list.isEmpty(),代码更简洁;​
  • Optional 更适合处理 “单个对象的 null”,而非 “集合的空”。​

正确示例:​

java取消自动换行复制

import org.apache.commons.collections4.CollectionUtils;​

public List<User> getAdultUsers(List<User> userList) {​

if (CollectionUtils.isEmpty(userList)) {​

return new ArrayList<>();​

}​

return userList.stream()​

.filter(user -> user.getAge() >= 18)​

.collect(Collectors.toList());​

}​

5.4 误区 4:滥用 orElse () 导致不必要的对象创建​

错误示例:​

java取消自动换行复制

避坑建议:​

  • 若默认值是 “需要创建的对象”(如 new User ()),优先使用orElseGet(),避免不必要的对象创建;​
  • 若默认值是 “常量”(如 "未知用户"),orElse()和orElseGet()均可使用,差异不大。​

正确示例:​

java取消自动换行复制

5.5 误区 5:在类的属性中使用 Optional​

错误示例:​

java取消自动换行复制

// 错误:在User类的属性中使用Optional,违反JavaBean规范​

class User {​

private String name;​

private Optional<Integer> age; // 不推荐:属性使用Optional​

// getter/setter会变得复杂​

public Optional<Integer> getAge() {​

return age;​

}​

public void setAge(Optional<Integer> age) {​

this.age = age;​

}​

}​

避坑建议:​

  • Optional 的设计初衷是 “方法返回值的空值处理”,而非 “类属性的存储”;​
  • 在类属性中使用 Optional 会违反 JavaBean 规范,导致 JSON 序列化 / 反序列化异常(如 Jackson 默认无法序列化 Optional 属性),且增加属性操作的复杂度。​

正确示例:​

java取消自动换行复制

// 正确:属性使用基本类型或包装类,null通过方法返回时用Optional处理​

class User {​

private String name;​

private Integer age; // 允许为null​

// 方法返回时用Optional处理空值​

public Optional<Integer> getAgeOptional() {​

return Optional.ofNullable(age);​

}​

// 普通getter,供内部使用​

public Integer getAge() {​

return age;​

}​

}​

5.6 误区 6:忽略 Optional 的异常处理(用 get () 前不判断)​

错误示例:​

java取消自动换行复制

// 错误:直接调用get(),未处理Empty状态,可能抛出NoSuchElementException​

public String getUserName(Long userId) {​

Optional<User> userOptional = Optional.ofNullable(userDao.getUserById(userId));​

// 风险:若user为null,抛出异常​

return userOptional.map(User::getName).get();​

}​

避坑建议:​

  • 永远不要直接调用get(),除非能 100% 确保 Optional 为 Present 状态;​
  • 优先使用orElse()、orElseGet()、orElseThrow()处理空值场景,强制覆盖所有可能的状态。​

正确示例:​

java取消自动换行复制

public String getUserName(Long userId) {​

return Optional.ofNullable(userDao.getUserById(userId))​

.map(User::getName)​

.orElse("未知用户"); // 明确处理空值​

}​

六、总结与最佳实践​

Optional 类是 Java 8 为空值处理提供的优雅解决方案,它通过 “容器化封装” 和 “链式调用”,消除了传统的嵌套 if 判断,强制开发者处理空值场景,从根源上减少了空指针异常的发生。但 Optional 并非 “万能药”,需在合适的场景中合理使用,才能发挥其最大价值。​

6.1 核心要点总结​

  1. 本质:Optional 是 “可能为 null 的对象容器”,包含 Present 和 Empty 两种状态,本身永远不为 null;​
  1. 方法分类:创建方法(of/ofNullable/empty)、中间操作(map/flatMap/filter)、终止操作(orElse/orElseGet/orElseThrow);​
  1. 核心优势:消除嵌套判断、强制空值处理、明确语义;​
  1. 适用场景:方法返回值的空值处理、对象属性的链式提取、业务异常的优雅抛出。​

6.2 最佳实践建议​

  1. 方法返回值优先用 Optional:若方法返回的对象 “可能为 null”(如数据库查询结果),优先返回 Optional,明确告知调用者需处理空值;​
  1. ** 优先使用 orElseGet () 替代 or
http://www.dtcms.com/a/581023.html

相关文章:

  • 面向强化学习的状态空间建模:RSSM的介绍和PyTorch实现(4)
  • openGauss安装部署详细教程
  • 用Visual Studio Code最新版开发C#应用程序
  • 修改llama index的prompte template(提示词模板)的解决方案
  • 在星河社区部署大模型unsloth/Llama-3.3-70B-Instruct-GGUF
  • 七家咨询公司的PPT标准配色模版(macos+Office LTSC Standard for Mac 2024)
  • 室内设计网站都有哪些平台五屏网站建设品牌
  • 11.7 脚本网站 中国象棋
  • rom定制系列------红米note10 5G版camellia_OS系统安卓14批量线刷双版root 原生等【二】
  • 【高阶数据结构学习笔记】高阶数据结构之B树B+树B*树
  • 基于Qt框架开发多功能视频播放器
  • 【FPGA】现场可编程门阵列
  • Android设备推送traceroute命令
  • SuperMap iObjects .NET 11i 二次开发(十七)—— 叠加分析之擦除
  • Verilog局部参数localparam
  • RS485总线通讯中一体化电机的PDO报文分析
  • 【MCU ATS323X】PM电源管理系统
  • 建网站一定要备案吗学生个人网站建设方案书框架栏目
  • 做兼职的网站都有哪些工作内容深圳建设网站首页
  • 【深入浅出】:人工智能从入门到实战
  • 日内瓦传动装置?不就是我们叫的间歇结构吗?
  • 基于SpringBoot的乡村支教全流程数字化管理平台 基于Django的智慧乡村支教综合管理系统 基于php与智能问答的乡村支教服务平台
  • dp|中位数贪心+裴蜀定理
  • 高集成低功耗RISC-V SoC收发芯片CI24R02
  • 中国科大创建乾坤网络精确求解多电子薛定谔方程
  • 世界著名的设计公司百度优化 几个网站内容一样
  • 【Debug】ChatGPT - Cli CodeX 登录报错 409 Route Error (409 ): 解决方案
  • C11期作业23(08.30)
  • 【JavaWeb】Tlias后台管理系统
  • 硬件工程师-基础知识电阻(四)