优雅地解决NullPointException

2023-05-16

null的困扰

通过上面代码示例,我们可以发现使用null可能会带来的一系列困扰:

  • 空指针异常,导致代码运行时变得不可靠,稍不留神可能就崩了
  • 使代码膨胀,导致代码中充斥大量的null检查与保护,使代码可读性降低

此外,null还有一个明显的弊端:

  • 含义不明确,比如一个方法返回了null,调用方不清楚到底是因为逻辑有问题导致为null,还是说null其实也是一种可以接受的正常返回值类型?

所以说,一个比较好的编码习惯,是尽量避免在程序中使用null,可以按照具体的场景分开区别对待:

  • 确定是因为代码或者逻辑层面处理错误导致的无值,通过throw异常的方式,强制调用方感知并进行处理对待
  • 如果null代表业务上的一种正常可选值,可以考虑返回Optional来替代。

当然咯,有时候即使我们自己的代码不返回null,也难免会遇到调用别人的接口返回null的情况,这种时候我们真的就只能不停的去判空来保护自己吗?有没有更优雅的应对策略来避免自己掉坑呢?下面呢,我们一起探讨下null的一些优雅应对策略。

Optional应对null处理

Optional一定比return null安全吗

前面我们提到了说使用Optional来替代null,减少调用端的判空操作压力,防止调用端出现空指针异常。

那么,使用返回Optional对象就一定会比return null更靠谱吗?

答案是:也不一定,关键要看怎么用!

比如:下面的代码,getContent()方法返回了个Optional对象,然后testCallOptional()方法作为调用方,获取到返回值后的操作方式:

public void testCallOptional() {
    Optional<Content> optional = getContent();
    System.out.println("-------下面代码会报异常--------");
    try {
        // 【错误用法】直接从Optional对象中get()实际参数,这种效果与返回null对象然后直接调用是一样的效果
        Content content = optional.get();
        System.out.println(content);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("-------上面代码会报异常--------");
}

private Optional<Content> getContent() {
    return Optional.ofNullable(null);
}
复制代码

上述代码运行之后会发现报错了:

-------下面代码会报异常--------
java.util.NoSuchElementException: No value present
	at java.util.Optional.get(Optional.java:135)
	at com.veezean.skills.optional.OptionalService.testCallOptional(OptionalService.java:47)
	at com.veezean.skills.optional.OptionalService.main(OptionalService.java:58)
-------上面代码会报异常--------
复制代码

既然直接调用Optional.get()报错,那就是调用前加个判断就好咯?

public void testCallOptional2() {
    Optional<Content> optional = getContent();
    // 使用前先判断下元素是否存在
    if (optional.isPresent()) {
        Content content = optional.get();
        System.out.println(content);
    }
}
复制代码

执行一下,果然不报错了。但是,这样真的就是解决方法吗?这样跟直接返回null然后使用前判空(下面的写法)其实也没啥区别,也并不会让调用方使用起来更加的优雅与靠谱:

public void testNullReturn2() {
    Content content = getContent2();
    if (content != null) {
        System.out.println(content.getValue());
    }
}
复制代码

那怎么样才是正确的使用方式呢,下面一起来看下。

全面认识下Optional

创建Optional对象

Optional<T>对象,可以用来表示一个T类型对象的封装,或者也可以表示不是任何对象。Optional类提供了几个静态方法供对象的构建:

方法名功能含义描述
empty()构造一个无任何实际对象值的空Optional对象(可以理解为业务层面的null
of(T t)根据给定的对象,构造一个此对象的封装Optional对象,注意入参t不能为null,否则会空指针
ofNullable(T t)根据传入的入参t的值构造Optional封装对象,如果传入的t为null,则等同于调用empty()方法,如果t不为null,则等同于调用of(T t)方法

在项目中,我们可以选择使用上面的方法,实现Optional对象的封装:

public void testCreateOptional() {
    // 使用Optional.of构造出具体对象的封装Optional对象
    System.out.println(Optional.of(new Content("111","JiaGouWuDao")));
    // 使用Optional.empty构造一个不代表任何对象的空Optional值
    System.out.println(Optional.empty());
    System.out.println(Optional.ofNullable(null));
    System.out.println(Optional.ofNullable(new Content("222","JiaGouWuDao22")));
}
复制代码

输出结果:

Optional[Content{id='111', value='JiaGouWuDao'}]
Optional.empty
Optional.empty
Optional[Content{id='222', value='JiaGouWuDao22'}]
复制代码

这里需要注意下of方法如果传入null会抛空指针异常,所以比较建议大家使用ofNullable方法,可以省去调用前的额外判空操作,也可以避免无意中触发空指针问题:

Optional常用方法理解

在具体讨论应该如何正确使用Optional的方法前,先来了解下Optional提供的一些方法:

方法名含义说明
isPresent如果Optional实际有具体对象值,则返回true,否则返回false。
ifPresent这是一个函数式编程风格的API接口,入参是一个函数,即如果Optional对象有实际对象值,则会执行传入的入参函数逻辑,如果不存在实际对象值,则不会执行传入的入参函数逻辑。
get返回Optional封装的实际对象T数据,注意,如果实际对象数据不存在,会抛异常而非返回null
orElseget方法类似,都是获取Optional实际的对象值,区别在于orElse必须传入一个默认值,当Optional没有实际值的时候返回默认值而非抛异常
orElseGet可以理解为orElse方法的升级版,区别在于orElse仅允许传入一个固定的默认值,而orElseGet的入参是一个函数方法,当Optional无实际值时,会执行给定的入参函数,返回动态值
orElseThroworElse类似,区别在于如果没有获取到,会抛出一个指定的异常
filter判定当前Optional的实际对象是否符合入参函数的过滤规则,如果符合则返回当前Optional对象,如果不符合则返回空Optional
map接收一个入参函数,允许将Optional中的实际对象值处理转换为另一实际对象值(这个入参函数的返回值为T),并生成返回此新类型的Optional对象,如果生成的新对象为null,则返回一个空Optional对象
flatMapmap类似,区别点在于入参函数的返回值类型有区别(此处入参函数的返回值为Optional<T>

看到这里的mapflatMap方法,不知道大家会不会联想到Stream流对象操作的时候也有这两个方法的身影呢(不了解的同学可以戳这个链接抓紧补补课:吃透JAVA的Stream流操作)?的确,它们的作用也是类似的,都是用来将一个对象处理转换为另一个对象类型的:

对于Optional而言,mapflatMap最终的实现效果其实都是一样的,仅仅只是入参的要求不一样,也即两种不同写法,两者区别点可以通过下图来理解:

实际使用的时候,可以根据需要选择使用map或者flatMap

public void testMapAndFlatMap() {
    Optional<User> userOptional = getUser();
    Optional<Employee> employeeOptional = userOptional.map(user -> {
        Employee employee = new Employee();
        employee.setEmployeeName(user.getUserName());
        // map与flatMap的区别点:此处return的是具体对象类型
        return employee;
    });
    System.out.println(employeeOptional);

    Optional<Employee> employeeOptional2 = userOptional.flatMap(user -> {
        Employee employee = new Employee();
        employee.setEmployeeName(user.getUserName());
        // map与flatMap的区别点:此处return的是具体对象的Optional封装类型
        return Optional.of(employee);
    });
    System.out.println(employeeOptional2);
}
复制代码

从输出结果可以看出,两种不同的写法,实现是相同的效果:

Optional[Employee(employeeName=JiaGouWuDao)]
Optional[Employee(employeeName=JiaGouWuDao)]
复制代码

Optional使用场景

减少繁琐的判空操作

再回到本篇文章最开始的那段代码例子,如果我们代码里面不去逐个做判空保护的话,我们可以如何来实现呢?看下面的实现思路:

public void getCompanyFromEmployeeTest() {
    Employee employeeDetail = getEmployee();
    String companyName = Optional.ofNullable(employeeDetail)
            .map(employee -> employee.getTeam())
            .map(team -> team.getDepartment())
            .map(department -> department.getCompany())
            .map(company -> company.getCompanyName())
            .orElse("No Company");
    System.out.println(companyName);
}
复制代码

先通过map的方式一层一层的去进行类型转换,最后使用orElse去获取Optional中最终处理后的值,并给定了数据缺失场景的默认值。是不是看着比一堆if判空操作要舒服多了?

📢 适用场景: 需要通过某个比较长的调用链路一层一层去调用获取某个值的时候,使用上述方法,可以避免空指针以及减少冗长的判断逻辑。

需要有值兜底的数据获取场景

编码的时候,经常会遇到一些数据获取的场景,需要先通过一些处理逻辑尝试获取一个数据,如果没有获取到需要的数据,还需要返回一个默认值,或者是执行另一处理逻辑继续尝试获取

比如从请求头中获取客户端IP的逻辑,按照常规逻辑,代码会写成下面这样:

public String getClientIp(HttpServletRequest request) {
    String clientIp = request.getHeader("X-Forwarded-For");
    if (!StringUtils.isEmpty(clientIp)) {
        return clientIp;
    }
    clientIp = request.getHeader("X-Real-IP");
    return clientIp;
}
复制代码

但是借助Optional来实现,可以这样写:

public String getClientIp2(HttpServletRequest request) {
    String clientIp = request.getHeader("X-Forwarded-For");
    return Optional.ofNullable(clientIp).orElseGet(() -> request.getHeader("X-Real-IP"));
}
复制代码

📢 适用场景: 优先执行某个操作尝试获取数据,如果没获取到则去执行另一逻辑获取,或者返回默认值的场景。

替代可能为null的方法返回值

下面是一段从项目代码中截取的片段:

public FileInfo queryOssFileInfo(String fileId) {
    FileEntity entity = fileRepository.findByIdAndStatus(fileId, 0);
    if (entity != null) {
        return new FileInfo(entity.getName(), entity.getFilePath(), false);
    }
    FileHistoryEntity hisEntity = fileHisRepository.findByIdAndStatus(fileId, 0);
    if (hisEntity != null) {
        return new FileInfo(hisEntity.getName(), hisEntity.getFilePath(), true);
    }
    return null;
}
复制代码

可以看到最终的return分支中,有一种可能会返回null,这个方法作为项目中被高频调用的一个方法,意味着所有的调用端都必须要做判空保护。可以使用Optional进行优化处理:

public Optional<FileInfo> queryOssFileInfo(String fileId) {
    FileEntity entity = fileRepository.findByIdAndStatus(fileId, 0);
    if (entity != null) {
        return Optional.ofNullable(new FileInfo(entity.getName(), entity.getFilePath(), false));
    }
    FileHistoryEntity hisEntity = fileHisRepository.findByIdAndStatus(fileId, 0);
    if (hisEntity != null) {
        return Optional.ofNullable(new FileInfo(hisEntity.getName(), hisEntity.getFilePath(), true));
    }
    return Optional.empty();
}
复制代码

这样的话,就可以有效的防止调用端踩雷啦~

📢 适用场景: 实现某个方法的时候,如果方法的返回值可能会为null,则考虑将方法的返回值改为Optional类型,原先返回null的场景,使用Optional.empty()替代。

包装数据实体中非必须字段

首先明确一下,Optional的意思是可选的,也即用于标识下某个属性可有可无的特性。啥叫可有可无?看下面代码:

public class PostDetail {
    private String title;
    private User postUser;
    private String content;
    private Optional<Date> lastModifyTime = Optional.empty();
    private Optional<Attachment> attachment = Optional.empty();
}
复制代码

上面是一个帖子详情数据类,对于一个论坛帖子数据而言,帖子的标题、内容、发帖人这些都是属于必须的字段,而帖子的修改时间、帖子的附件其实是属于可选字段(因为不是所有的帖子都会被修改、也不是所有帖子都会带附件),所以针对这种可有可无的字段,就可以声明定义的时候使用Optional进行封装。

使用Optional进行封装之后有两个明显的优势:

  • 强烈的业务属性说明,明确的让人知晓这个是一个可选字段,等同于数据库建表语句里面设置nullable标识一样的效果;
  • 调用端使用的时候也省去了判空操作。

📢 适用场景: 数据实体定义的时候,对于可选参数,采用Optional封装类型替代。

使用抛异常替代return null

相比于返回一个Optional封装的对象,直接抛异常具有强烈的警醒意味,意在表达此处存在预期之外的不合理情况,要求编码的时候,调用端必须要予以专门处理

public Team getTeamInfo() throws TestException {
    Employee employee = getEmployee();
    Team team = employee.getTeam();
    if (team == null) {
        throw new TestException("team is missing");
    }
    return team;
}
复制代码

相比直接return null,显然抛异常的含义更加明确。

JDK与开源框架的实践

JDK提供的很多方法里面,其实都是遵循着本文中描述的这种返回值处理思路的,很少会看到直接返回null的——不止JDK,很多大型的开源框架源码中,也很少会看到直接return null的情况。

比如com.sun.jmx.snmp.agent中的一段代码:

public SnmpMibSubRequest nextElement() throws NoSuchElementException  {
    if (iter == 0) {
        if (handler.sublist != null) {
            iter++;
            return hlist.getSubRequest(handler);
        }
    }
    iter ++;
    if (iter > size) throw new NoSuchElementException();
    SnmpMibSubRequest result = hlist.getSubRequest(handler,entry);
    entry++;
    return result;
}
复制代码

再比如Spring中org.springframework.data.jpa.repository.support包下面的方法例子:

public Optional<T> findById(ID id) {
	Assert.notNull(id, ID_MUST_NOT_BE_NULL);
	Class<T> domainType = getDomainClass();
	if (metadata == null) {
		return Optional.ofNullable(em.find(domainType, id));
	}
	LockModeType type = metadata.getLockModeType();
	Map<String, Object> hints = getQueryHints().withFetchGraphs(em).asMap();
	return Optional.ofNullable(type == null ? em.find(domainType, id, hints) : em.find(domainType, id, type, hints));
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

优雅地解决NullPointException 的相关文章

  • 用word发CSDN blog,免去插图片的烦恼

    用csdn自带的网页编辑器 xff0c 最不方便的 xff0c 不是排版 xff0c 而是图片的发布 xff0c 希望能通过下面这个方式得到改善 1 注册博客账号 1 1 打开一个新的Word文档 如果之前没有用过博客功能的话 xff0c
  • openstack如何支持vlan trunk功能

    大多数场景下 xff0c 主机收发的是不带tag的报文 xff0c 但是在实际环境中 xff0c 无论是windows还是Linux环境都通过各自的方法可以收发带有vlan tag的报文 而一个虚机要想接收不同vlan tag的报文 xff
  • 在vscode中调试webpack

    前言 接手了公司的新项目 xff0c 但是由于对整个运作流程不了解 xff0c 想要一步步进行调试加深对项目印象 xff0c 所以搜索了相关资料 xff0c 结合自己实际情况进行调试 调试的两个关键文件 package json 正常的pa
  • AD和DA转换-第1季第16部分-朱有鹏-专题视频课程

    AD和DA转换 第1季第16部分 2091人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第1季第16个课程 xff0c 主要讲解AD转换和DA转换 目标是理解模拟量和数字量的概念 xff0c 并且学会使用AD转换来采集现实
  • vnc viewer登陆问题

    这里操作的前提是已经 安装了vnc server 登陆SUN 210 server xff0c solaris 10 采用VNC viewer 但是并不是每次登陆都成功 开始总是不成功 采用以下两条命令 xff1a vncserver ki
  • 光谱分布、光谱辐射通量密度与不同时间段分布光谱(图示)

    1 光谱分布图 2 太阳辐射能量图 3 不同时间段的太阳分布光谱图 4 不同波长的光的能量分布主要区域 5 不同波段的使用场景
  • 电磁波波谱及不同波长成像图

    1 电磁辐射波 实际的图像处理应用中 xff0c 最主要的图像来源于电磁 辐射成像 电磁辐射波包括无线电波 微波 红外线 可见光 紫外线 X射线 射线 电磁辐射波的波谱范围很广 xff0c 波长最长的是无线电波 为3 102m xff0c
  • 写给VR手游开发小白的教程:(四)补充篇,详细介绍Unity中相机的投影矩阵

    这篇作为上一篇的补充介绍 xff0c 主要讲Unity里面的投影矩阵的问题 xff1a 上篇的链接写给VR手游开发小白的教程 xff1a xff08 三 xff09 UnityVR插件CardboardSDKForUnity解析 xff08
  • 阿里云centos修改ssh端口后连接失败

    话说本人虽然工作多年 xff0c 一直是linux小白一个 xff0c 估计像我这样的也是没谁了 每次面试的时候面试官一问是否会linux xff0c 都老脸一红啊 为了解决这种情况 xff0c 自己去阿里云买了一台centos的服务器 x
  • linux进程调度方法(SCHED_OTHER,SCHED_FIFO,SCHED_RR)

    linux内核的三种调度方法 xff1a 1 xff0c SCHED OTHER 分时调度策略 xff0c 2 xff0c SCHED FIFO实时调度策略 xff0c 先到先服务 3 xff0c SCHED RR实时调度策略 xff0c
  • 12- 降维算法 (PCA降维/LDA分类/NMF) (数据处理)

    数据降维就是一种对高维度特征数据预处理方法 降维是将高维度的数据保留下最重要的一些特征 xff0c 去除噪声和不重要的特征 xff0c 从而实现提升数据处理速度的目的 PCA算法有两种实现方法 xff1a 基于特征值分解协方差矩阵实现PCA
  • 软件体系整理5-6章

    第五章 软件体系结构风格 1 管道过滤器风格 特征 xff1a xff08 1 xff09 构件即过滤器 xff08 Filter xff09 xff0c 对输入流进行处理 转换 xff0c 处理后的结果在输出端流出 而且 xff0c 这种
  • Hive中的DDL操作

    参考文章 xff1a https www cnblogs com qingyunzong p 8723271 html 官方文档 xff1a https cwiki apache org confluence display Hive La
  • linux echo输出结果赋值给变量,shell变量n位补零

    name 61 96 echo 1 awk 39 printf 34 04d n 34 0 39 96 将 1 进行4位数补零 xff0c 后传递字符串给 name 将下面代码 xff0c 命名为 playVideo sh 的shell脚本
  • LCD1602和12864显示器-第1季第17部分-朱有鹏-专题视频课程

    LCD1602和12864显示器 第1季第17部分 3539人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第1季第17个课程 xff0c 主要讲解LCD1602和LCD12864这两种单片机常用LCD显示器的显示原理 以及
  • CV小白实践--实现MNIST手写数字识别时遇到的问题

    1 RuntimeError size mismatch m1 800 x 4 m2 320 x 50 问题原因 xff1a 这个问题出现在神经网络最后一层卷积层与第一层全连接层之间 首先来看一下我实现的神经网络的结构 def init s
  • Hbase中Scan数据时的缓存优化以scan 过滤器的使用

    1 缓存优化 在hbase的java api 中 默认在scan 过程中scan next一次进行一次rpc请求 这导致scan的效率很低 设置scan的缓存优化很有必要 1 scan setBatch int 10 设置一次next 返回
  • 人脸识别之人脸检测(三)--Haar特征原理及实现

    本文主要由于OpenCV的haartraining程序 xff0c 对haar特征的补充及代码注释 原文 xff1a http www aiuxian com article p 2476165 html Haar特征的原理是什么 xff1
  • 网络基础(一)【解决mininet中xterm域名无法解析的问题】

    mininet是一个很好用的网络仿真实验平台 xff0c 基于网络命名空间技术的python封装 我是在linux虚拟机中安装了mininet环境 sudo mn mininet gt xterm h1 h2 启动一个xterm程序 xff

随机推荐

  • 多任务学习:Multi-Task Learning as Multi-Objective Optimization

    前言 最近在写一篇文章 xff0c 是一篇深度学习与安全相结合的文章 xff0c 模型的输出会交给两个损失函数 xff08 availability amp security xff09 进行损失计算 xff0c 进而反向传播 起初的想法是
  • 浅析Linux命令之alias

    转自 xff1a http man linuxde net alias 1 作用 用来设置指令的别名 我们可以使用该命令将一些较长的命令进行简化 使用alias时 xff0c 必须使用单引号将原来的命令引起来 xff0c 防止特殊字符导致错
  • Verilog实现串口通讯(UART)

    Verilog实现串口通讯 xff08 UART xff09 本代码参考了野火的相关教程 xff0c 实现了发送和接收回环 xff0c 同时可以通过串口数据控制LED灯的亮灭 xff0c 在电脑发送数据时要选择HEX发送模式 xff0c 发
  • Ubuntu 查看硬盘容量

    在服务器节点上使用硬盘较多 xff0c 被强制清盘多次 xff0c 清盘时需要查看文件夹占用情况 xff0c 并考虑是否重要来决定删除 因此必不可少一些查看硬盘占用的命令 1 du s h 43 路径 du s h 查看home目录下占用总
  • Matlab R2018a初始化问题

    前几天装的MATLAB2018 xff08 我装在C盘 xff0c 用的是在线安装 xff0c 自己下的License 破解了 xff09 xff0c 但是初始化问题一直没解决 xff0c 下面显示我遇到的问题 xff1a 等4 5分钟才就
  • vnc view安装与使用

    vnc view安装与使用 1 安装 vnc远程连接 xff0c 需要在服务器端安装vnc server 在客户端安装vnc viewer 这里我主要是研究如何在自己的电脑安装vnc viewer xff0c 来远程连接服务器 1 xff0
  • 温度传感器DS18B20-第2季第1部分-朱有鹏-专题视频课程

    温度传感器DS18B20 第2季第1部分 1700人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第2季第1个课程 xff0c 主要讲解单片机系统中常用的温度传感器DS18B20 本课程的目标是让大家进一步掌握时序的分析和编
  • Shell删除某个文件夹下指定字符开头的所有文件

    工作中遇到过日志文件夹里面存放的日志数量太多 xff0c 直接使用rm rf 删除提示参数太多 xff0c 其实是因为要删除的文件太多 xff0c 没法一次全部删除 xff0c 具体rm rf能够一次删除的数量是多少就不知道了 xff0c
  • Ubuntu 11.10 远程桌面Windows设置

    升级到Ubuntu 11 10时原来远程客户端tsclient不能用了 xff0c 那么怎么办 xff1f 两个途径可以 xff1a 1 Remmina远程桌面客户端 xff0c 如果在互联网下没有 xff0c 在新立得下安装即可 设定几乎
  • 模型的学习方式-迁移学习、多任务学习、小样本学习、元学习

    前言 无论是有监督学习还是无监督学习 半监督学习 无论算法是什么 xff0c 一直感觉机器学习 深度学习模型都是一种数据驱动的 换句话说 xff0c 足够且有质量的数据 xff0c 才能让模型学到一定的知识 xff0c 达到比较理想的效果
  • 【CVPR2019_论文汇总】(按方向划分,0401 更新中)

    转载链接 xff1a http bbs cvmart net topics 302 cvpr2019paper 作为计算机视觉领域三大顶会之一 xff0c CVPR2019 xff08 2019 6 16 6 19在美国洛杉矶举办 xff0
  • 基于MATLAB的卷积神经网络车牌识别系统

    车牌识别是基于车牌照片的车牌信息的识别工作 xff0c 车牌识别技术对我们的实际生活至关重要 xff0c 例如交通违规行为的增加 xff0c 拦截非法车辆 xff0c 在速度上能够进行快速识别能够很好地解决这些问题 获得的照片的质量是影响车
  • 互连网络的定义

    原文 xff1a http julong com cn Service FAQview asp FAQID 61 15 互联网络是一通过中间网络设备连接多个独立网络的集合 xff0c 其功能是形成一个覆盖范围更广的网络 网络互联技术意指工业
  • Win11本地安装Ubuntu 22.04 双系统简易教程

    1 制作启动U盘 首先找到一个硬盘容量不小于4G的空U盘 xff0c 需要对其进行格式化 然后下载Ubuntu 22 04的iso文件到本地 Ubuntu 22 04 1 LTS 中国地区下载链接 下载 UltraISO并制作启动U盘 Ul
  • 图文详解VMWare Workstation安装Ubuntu20.04虚拟机

    图文详解VMWare Workstation安装Ubuntu20 04虚拟机 0 准备工作1 新建虚拟机并进行初始配置2 安装虚拟机系统 0 准备工作 在使用VMWare Workstation进行Ubuntu20 04虚拟机安装前 xff
  • 理解数据库中的undo日志、redo日志、检查点

    数据库存放数据的文件 xff0c 本文称其为data file 数据库的内容在内存里是有缓存的 xff0c 这里命名为db buffer 某次操作 xff0c 我们取了数据库某表格中的数据 xff0c 这个数据会在内存中缓存一些时间 对这个
  • Token原理

    Q xff1a 分布式场景下如何生成token以及使用token的流程 xff1a 在分布式场景下 xff0c 可以采用以下方式生成 token 和进行权限认证 xff1a 1 生成 token xff1a 使用JWT xff08 JSON
  • 红外遥控其实so easy-第2季第2部分-朱有鹏-专题视频课程

    红外遥控其实so easy 第2季第2部分 1521人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第2季第2个课程 xff0c 主要讲解如何用单片机进行红外遥控解码 红外遥控是家电产品常用的控制方法 xff0c 通过本课程
  • idea ctrl+左键找到方法引用,选择 All Places的方法

    有时候在idea里点击某个方法想找到该方法在所有地方的引用 xff0c 但是有时候会发现idea默认是在项目文件里搜索 xff0c 这样就搜索不到jar包里的引用 xff0c 如果没有搜到项目里的引用 xff0c 弹窗就会一闪而过 xff0
  • 优雅地解决NullPointException

    null的困扰 通过上面代码示例 xff0c 我们可以发现使用null可能会带来的一系列困扰 xff1a 空指针异常 xff0c 导致代码运行时变得不可靠 xff0c 稍不留神可能就崩了使代码膨胀 xff0c 导致代码中充斥大量的null检