返回顶部
首页 > 资讯 > 精选 >JAVA8怎么用Optional解决NPE问题
  • 467
分享到

JAVA8怎么用Optional解决NPE问题

2023-06-15 20:06:53 467人浏览 泡泡鱼
摘要

本篇内容主要讲解“JAVA8怎么用Optional解决NPE问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JAVA8怎么用Optional解决NPE问题”吧! 引言NPE(Null

本篇内容主要讲解“JAVA8怎么用Optional解决NPE问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JAVA8怎么用Optional解决NPE问题”吧!

JAVA8怎么用Optional解决NPE问题

 引言

NPE(NullPointerException)是调试程序最常见的异常。Google一下有很多关于方法到底应该返回null还是new一个空对象的讨论。

在文章的开头,先说下NPE问题,NPE问题就是,我们在开发中经常碰到的NullPointerException.假设我们有两个类,他们的UML类图如下图所示

JAVA8怎么用Optional解决NPE问题

在这种情况下,有如下代码:

user.getAddress().getProvince();

这种写法,在user为null时,是有可能报NullPointerException异常的。为了解决这个问题,于是采用下面的写法:

if(user!=null){  Address address = user.getAddress();  if(address!=null){  String province = address.getProvince();  } }

这种写法是比较丑陋的,为了避免上述丑陋的写法,让丑陋的设计变得优雅。JAVA8提供了Optional类来优化这种写法,接下来的正文部分进行详细说明

API介绍

先介绍一下api,与其他文章不同的是,本文采取类比的方式来讲,同时结合源码。而不像其他文章一样,一个个API罗列出来,让人找不到重点。

(1)Optional(T value),empty(),of(T value),ofNullable(T value)

这四个函数之间具有相关性,因此放在一组进行记忆。

先说明一下,Optional(T  value),即构造函数,它是private权限的,不能由外部调用的。其余三个函数是public权限,供我们所调用。那么,Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。好吧,这么说还是比较抽象。直接上Optional(T  value)构造函数的源码,如下图所示

JAVA8怎么用Optional解决NPE问题

那么,of(T value)的源码如下:

public static <T> Optional<T> of(T value) {  return new Optional<>(value);  }

也就是说of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:

(1)通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。

(2)通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。

除此之外呢,Optional类内部还维护一个value为null的对象,大概就是长下面这样的

public final class Optional<T> {  //省略....  private static final Optional<?> EMPTY = new Optional<>();  private Optional() {  this.value = null;  }  //省略...  public static<T> Optional<T> empty() {  @SuppressWarnings("unchecked")  Optional<T> t = (Optional<T>) EMPTY;  return t;  } }

那么,empty()的作用就是返回EMPTY对象。

好了铺垫了这么多,可以说ofNullable(T value)的作用了,上源码:

public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }

相比较of(T value)的区别就是,当value值为null时,of(T  value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T  value)直接返回一个EMPTY对象。

那是不是意味着,我们在项目中只用ofNullable函数而不用of函数呢?

不是的,一个东西存在那么自然有存在的价值。当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。但是不得不承认,这样的场景真的很少。博主也仅在写junit测试用例中用到过此函数。

(2)orElse(T other),orElseGet(Supplier  other)和orElseThrow(Supplier exceptionSupplier)

这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。orElse和orElseGet的用法如下所示,相当于value值为null时,给予一个默认值:

@Test public void test() {  User user = null;  user = Optional.ofNullable(user).orElse(createUser());  user = Optional.ofNullable(user).orElseGet(() -> createUser());    }   public User createUser(){  User user = new User();  user.setName("zhangsan");  return user; }

这两个函数的区别:当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法,大家可自行测试。

至于orElseThrow,就是value值为null时,直接抛一个异常出去,用法如下所示:

User user = null; Optional.ofNullable(user).orElseThrow(()->new Exception("用户不存在"));

(3) map(Function mapper)和flatMap(Function mapper)

这两个函数放在一组记忆,这两个函数做的是转换值的操作。

直接上源码,如下:

public final class Optional<T> {  //省略....   public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {   Objects.requireNonNull(mapper);   if (!isPresent())    return empty();   else {    return Optional.ofNullable(mapper.apply(value));   }  }  //省略...   public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {   Objects.requireNonNull(mapper);   if (!isPresent())    return empty();   else {    return Objects.requireNonNull(mapper.apply(value));   }  } }

这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Function,而flapMap的入参类型为Function。

在具体用法上,对于map而言:

如果User结构是下面这样的

public class User {  private String name;  public String getName() {   return name;  } }

这时候取name的写法如下所示

String city = Optional.ofNullable(user).map(u-> u.getName()).get();

对于flatMap而言:

如果User结构是下面这样的

public class User {  private String name;  public Optional<String> getName() {   return Optional.ofNullable(name);  } }

这时候取name的写法如下所示:

String city = Optional.ofNullable(user).flatMap(u-> u.getName()).get();

(4) isPresent()和ifPresent(Consumer consumer)

这两个函数放在一起记忆,isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。这两个函数的源码如下

public final class Optional<T> {  //省略....  public boolean isPresent() {   return value != null;  }  //省略...  public void ifPresent(Consumer<? super T> consumer) {   if (value != null)    consumer.accept(value);  } }

需要额外说明的是,大家千万不要把

if (user != null){  // TODO: do something }

给写成

User user = Optional.ofNullable(user); if (Optional.isPresent()){  // TODO: do something }

因为这样写,代码结构依然丑陋。博主会在后面给出正确写法

至于ifPresent(Consumer consumer),用法也很简单,如下所示:

Optional.ofNullable(user).ifPresent(u->{    // TODO: do something   });

(5) filter(Predicate predicate)

不多说,直接上源码:

public final class Optional<T> {  //省略....  Objects.requireNonNull(predicate);   if (!isPresent())    return this;   else    return predicate.test(value) ? this : empty(); }

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个  Optional;否则返回 Optional.empty。

用法如下:

Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);

如上所示,如果user的name的长度是小于6的,则返回。如果是大于6的,则返回一个EMPTY对象。

实战使用

例一

在函数方法中

以前写法

public String getCity(User user) throws Exception{   if(user!=null){    if(user.getAddress()!=null){     Address address = user.getAddress();     if(address.getCity()!=null){      return address.getCity();     }    }   }   throw new Excpetion("取值错误");   }

JAVA8写法

public String getCity(User user) throws Exception{  return Optional.ofNullable(user)      .map(u-> u.getAddress())      .map(a->a.getCity())      .orElseThrow(()->new Exception("取指错误")); }

例二

比如,在主程序中

以前写法

if(user!=null){  dosomething(user); }

JAVA8写法

Optional.ofNullable(user)   .ifPresent(u->{   dosomething(u);   });

例三

以前写法

public User getUser(User user) throws Exception{  if(user!=null){   String name = user.getName();   if("zhangsan".equals(name)){    return user;   }  }else{   user = new User();   user.setName("zhangsan");   return user;  } }

java8写法

ublic User getUser(User user) {  return Optional.ofNullable(user)      .filter(u->"zhangsan".equals(u.getName()))      .orElseGet(()-> {       User user1 = new User();       user1.setName("zhangsan");       return user1;      }); }

说明:链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。

到此,相信大家对“JAVA8怎么用Optional解决NPE问题”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: JAVA8怎么用Optional解决NPE问题

本文链接: https://lsjlt.com/news/281400.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JAVA8怎么用Optional解决NPE问题
    本篇内容主要讲解“JAVA8怎么用Optional解决NPE问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JAVA8怎么用Optional解决NPE问题”吧! 引言NPE(Null...
    99+
    2023-06-15
  • JAVA8妙用Optional解决判断Null为空的问题方法
    目录引言API介绍1、Optional(T value),empty(),of(T value),ofNullable(T value)2、orElse(T other),orEls...
    99+
    2024-04-02
  • Java8新特性Optional类怎么应用
    这篇“Java8新特性Optional类怎么应用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java8新特性Optiona...
    99+
    2023-06-29
  • Optional怎么中Java8 项目中使用
    这篇文章给大家介绍Optional怎么中Java8 项目中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允...
    99+
    2023-06-06
  • Jackson处理Optional时遇到问题的解决与分析
    目录前言目录正文1. 序列化Optional类型的问题2. 原因分析3. 解决办法总结前言 Optional是Java8中增加的一个特性,它的出现是为了解决Java中的空指针问题,相...
    99+
    2024-04-02
  • Django使用问题怎么解决
    本篇内容介绍了“Django使用问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Django R...
    99+
    2024-04-02
  • 怎么使用github解决问题
    在当今软件开发行业中,Github已经成为了解决问题的一个重要工具。Github是一个面向开源及私有软件项目的托管平台,因为其丰富的特性得到了全球开发者的广泛喜爱。在利用Github解决问题时,需要注意以下几个方面。一、Github是什么G...
    99+
    2023-10-22
  • 怎么用Python解决Excel问题
    本篇内容介绍了“怎么用Python解决Excel问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!「问题说明」这次要处理的excel有两个s...
    99+
    2023-07-06
  • 怎么用java解决背包问题
    背包问题是一个经典的组合优化问题,可以使用动态规划来解决。以下是使用Java语言解决背包问题的一个示例: public class ...
    99+
    2023-10-24
    java
  • Vue router应用问题怎么解决
    这篇文章主要讲解了“Vue router应用问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue router应用问题怎么解决”吧!问题记录路由守卫的应用根据...
    99+
    2023-06-30
  • Vue使用swiper问题怎么解决
    本文小编为大家详细介绍“Vue使用swiper问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue使用swiper问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、下载指定版本swipe...
    99+
    2023-07-06
  • 怎么使用Puppeteer解决SEO问题
    这篇文章主要讲解了“怎么使用Puppeteer解决SEO问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用Puppeteer解决SEO问题”吧!引言在前端开发中,我们经常会遇到SEO...
    99+
    2023-07-05
  • 怎么解决SQLServer IDENTITY_INSERT问题
    这篇文章主要介绍“怎么解决SQLServer IDENTITY_INSERT问题”,在日常操作中,相信很多人在怎么解决SQLServer IDENTITY_INSERT问题问题上存在疑惑,小编查阅了各式资料...
    99+
    2024-04-02
  • MySQL Backup问题怎么解决
    这篇文章主要讲解了“MySQL Backup问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL Backup问题怎么解决”吧!#!/bin...
    99+
    2024-04-02
  • 怎么解决Multipath的问题
    这篇文章主要讲解了“怎么解决Multipath的问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决Multipath的问题”吧!今天使用Packer...
    99+
    2024-04-02
  • Solaris awk问题怎么解决
    这篇文章主要介绍“Solaris awk问题怎么解决”,在日常操作中,相信很多人在Solaris awk问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Solaris awk问题怎么解决”的疑惑有所...
    99+
    2023-06-05
  • Linux makefile问题怎么解决
    这篇文章主要讲解了“Linux makefile问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux makefile问题怎么解决”吧!将各个模块的关系写进makefile,...
    99+
    2023-06-17
  • Hibernate session问题怎么解决
    这篇文章主要介绍“Hibernate session问题怎么解决”,在日常操作中,相信很多人在Hibernate session问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Hibernate s...
    99+
    2023-06-17
  • IDEA Debug问题怎么解决
    这篇文章主要讲解了“IDEA Debug问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“IDEA Debug问题怎么解决”吧!问题引入最近看了 eclipse ...
    99+
    2023-07-04
  • linux ftp530问题怎么解决
    这篇“linux ftp530问题怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“l...
    99+
    2023-03-14
    linux ftp
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作