空指针是我们 Java 开发人员经常遇到的一个基本异常,这是一个极其普遍但似乎又无法根治的问题。

本文将带你了解什么是空指针,以及如何有效的避免空指针。

什么是空指针?

当一个变量的值为 null 时,在 Java 里面表示一个不存在的空对象,没有实际内容,没有给它分配内存,null 也是对象成员变量的默认值。所以,一个对象如果没有进行初始化操作,这时候,如果你调用这个对象的方法或者变量,就会出现空指针异常。
如示例会发生空指针异常:


Object object = null;
String string = object.toString();

上述情况中,空指针它是属于运行时异常 RuntimeException 的子类,它不是捕获型的,在程序运行时随时可能报出来,而且会造成程序中断。

如何避免空指针

下面说几个空指针的几个最常见的案例及解决之道。

1、字符串比较,常量放前面


if(status.equals(SUCCESS)){}

这个时候 status 可能为 null 造成空指针异常,应该把常量放前面,就能避免空指针异常。


if(SUCCESS.equals(status)){}

2、初始化NULL,指定默认值


User user = NULL;
String name = NULL;

在对象初始化的时候给它一个默认值或者默认构造实现,如:


User user = new User();
String name = StringUtils.EMPTY;

3、返回值为NULL,返回空集合

在返回一个集合的话,默认会是 null,统一规范返回一个空集合。

举个 List 例子,如:

public List getUserList(){List list = userMapper.gerUserList();return list == null ? new ArrayList() : list;
}

这样接收方就不用担心空指针异常了,也不会影响业务。

4、断言

断言是用来检查程序的安全性的,在使用之前进行检查条件,如果不符合条件就报异常,符合就继续。

Java 中自带的断言关键字:assert,如:


assert name == null : “名称不能为空”;

Exception in thread “main” java.lang.AssertionError: 名称不正确
不过默认是不启动断言检查的,需要要带上 JVM 参数:-enableassertions 才能生效。

Java 中这个用的很少,建议使用 Spring 中的,更强大,更方便好用。

Spring中的用法:


Assert.notNull(name,“名称不能为空”);

5、Optional

Optional 是 JDK 8 新增的新特性,再也不用 != null 来判断了。


// book 存在则执行打印
Optional<Book> optBook = Optional.of(book);
optBook.ifPresent(book -> System.out.println(book.getName()));

// book 为NULL,则返回默认值
Optional<Book> optBook = Optional.of(book);
String bookName = optBook.orElse("Unknown");

// book 为NULL,则返回默认值
Optional<Book> optBook = Optional.of(book);
String bookName = optBook.orElse("Unknown");

你可以使用 of() 和 ofNullable() 方法创建包含值的 Optional。两个方法的不同之处在于如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException,而 ofNullable() 不会。

// user 对象是空的,则返回了作为默认值的 user2
@Test
public void whenEmptyValue_thenReturnDefault() {User user = null;User user2 = new User("anna@gmail.com", "1234");User result = Optional.ofNullable(user).orElse(user2);assertEquals(user2.getEmail(), result.getEmail());
}

// 存在即返回,无则提供默认值
return user.orElse(UNKNOWN_USER); //而不是 return user.isPresent() ? user.get() : null;// 存在即返回, 无则由函数来产生
return user.orElseGet(() -> fetchAUserFromDatabase());// 使用map
return user.map(u -> u.getOrders()).orElse(Collections.emptyList())// 上面避免了类似 Java 8 之前的做法
if(user.isPresent()) {return user.get().getOrders();
} else {return Collections.emptyList();
}

// filter 如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional
@Test
public void useJava8() {List<Student> studentList = initData();for (Student student : studentList) {Optional<Student> studentOptional = Optional.of(student);// 如果年龄大于18则返回Student的Optional// 返回Score的Optional// Score为null则返回0Integer score = studentOptional.filter(s -> s.getAge() >= 18).flatMap(Student::getScore).orElse(0);if (score > 80) {System.out.println("入选:" + student.getName());}}
}

空值


Collections.emptyList();
StringUtils.EMPTY;

Optional 使用介绍

  1. 创建:

    Optional.empty(): 创建一个空的 Optional 实例

    Optional.of(T t):创建一个 Optional 实例,当 t为null时抛出异常

    Optional.ofNullable(T t):创建一个 Optional 实例,但当 t为null时不会抛出异常,而是返回一个空的实例

  2. 获取:

    get():获取optional实例中的对象,当optional 容器为空时报错

  3. 判断:

    isPresent():判断optional是否为空,如果空则返回false,否则返回true

    ifPresent(Consumer c):如果optional不为空,则将optional中的对象传给Comsumer函数

    orElse(T other):如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值

    orElseGet(Supplier other):如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other

    orElseThrow(Supplier exception):如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常

  4. 过滤:

    filter(Predicate p):如果optional不为空,则执行断言函数p,如果p的结果为true,则返回原本的optional,否则返回空的optional

  5. 映射:

    map(Function<T, U> mapper):如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。

    flatMap(Function< T,Optional> mapper) 跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional

    区别:map会自动将u放到optional中,而flatMap则需要手动给u创建一个optional

java之空指针异常处理相关推荐

  1. java catch空指针异常处理_Java基础学习:java文件空指针异常处理

    在Java编程中,我们或多或少地会遇到一些程序异常的情况,为了不影响程序的正常执行,我们需要在程序发生异常的情况下,进行一些操作来防止造成更大的损失.例如在我们平时的除法运算中,被除数是不能为0的,如 ...

  2. 阿里巴巴对Java编程【异常处理】的规约

    转载自 阿里巴巴对Java编程[异常处理]的规约 异常处理 1. [强制] Java 类库中定义的一类 RuntimeException 可以通过预先检查进行规避,而不应该通过 catch 来处理,比 ...

  3. 【转】Java中关于异常处理的十个最佳实践

    原文地址:http://www.searchsoa.com.cn/showcontent_71960.htm 导读:异常处理是书写强健Java应用的一个重要部分,Java许你创建新的异常,并通过使用 ...

  4. 【Java面试题】21 Java中的异常处理机制的简单原理和应用。

    [Java面试题]21 Java中的异常处理机制的简单原理和应用. 参考文章: (1)[Java面试题]21 Java中的异常处理机制的简单原理和应用. (2)https://www.cnblogs. ...

  5. Java中的异常处理:何时抛出异常,何时捕获异常?

    Java中的异常处理:何时抛出异常,何时捕获异常? 参考文章: (1)Java中的异常处理:何时抛出异常,何时捕获异常? (2)https://www.cnblogs.com/tsiangleo/p/ ...

  6. java.lang.IllegalArgumentException异常处理的一种方法

    java.lang.IllegalArgumentException异常处理的一种方法 参考文章: (1)java.lang.IllegalArgumentException异常处理的一种方法 (2) ...

  7. 第八节:详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架

    前言 大家好,给大家带来详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架的概述,希望你们喜欢 JAVA 异常 try...catch...finally结构的使用方法 class Tes ...

  8. 【Java】Java中的异常处理:何时抛出异常,何时捕获异常?

    参考文章:Java中的异常处理:何时抛出异常,何时捕获异常? 参考文章:Python错误处理-廖雪峰的官方网站 1 异常分类 Throwable对象可以分为两组: 一组是unchecked异常,异常处 ...

  9. Java进阶02 异常处理

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 程序很难做到完美,不免有各种各样的异常.比如程序本身有bug,比如程序打印时打印机 ...

最新文章

  1. IT创业迷魂圈:不要画饼充饥
  2. jquery基本操作
  3. 【小白学习C++ 教程】二十一、C++ 中的STL容器Arrays和vector
  4. 流量节省模式 Android,这三种方法让你节省更多手机上网流量
  5. php和web服务器,php与web服务器关系
  6. 两个字符串的最长公共子序列长度_程序员编程算法,解决文本相似度问题的最长公共子序列算法!...
  7. cba篮球暂停次数和时间_为什么足球赛的观赏性比篮球更强?这三点是主要原因...
  8. 发现 nios2-elf-gcc 一处 bug
  9. 简述html文档的基本,网页制作简答题答案
  10. java RSA加密生成license,用CPU序列号生成机器码
  11. WeUi使用手册及参考
  12. idea背景颜色修改
  13. sql盲注 解决_SQL盲注攻击的简单介绍
  14. JS设置cookie,获取cookie
  15. java 获取excel的行数_关于Java:如何使用POI库获取Excel文件中的行数?
  16. Edge浏览器配置教程
  17. python+django+vue高校奖学金评定管理系统
  18. 联通的沃phone相关新闻
  19. F5 LTM ping 数据包丢包解决过程
  20. 二阶Volterra矩阵生成 matlab

热门文章

  1. 崩坏2服务器维护,崩坏学园2(日服)无法连接服务器是什么原因
  2. python图片保存jpg、show变成bmp_Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中...
  3. easywechat6获取微信用户信息(基于公众号)
  4. UE4 角色上下车功能
  5. 主机和虚拟机实现复制粘贴功能
  6. django 解析上传xls文件
  7. 【智能硬件】Jetson nana 扩展显存(内存)
  8. 3dsmax-拓扑插件Wrapit使用
  9. 说一下国内做MES的几类厂商
  10. poi在word输出复选框windows远程突然不能复制的解决方法