在写代码的时候,Idea经常会提醒我们可以使用这个方法来进行参数非空检查, 这个方法的源码也非常简单, 如下所示:

/*** Checks that the specified object reference is not {@code null}. This* method is designed primarily for doing parameter validation in methods* and constructors, as demonstrated below:* <blockquote><pre>* public Foo(Bar bar) {*     this.bar = Objects.requireNonNull(bar);* }* </pre></blockquote>** @param obj the object reference to check for nullity* @param <T> the type of the reference* @return {@code obj} if not {@code null}* @throws NullPointerException if {@code obj} is {@code null}*/
public static <T> T requireNonNull(T obj) {if (obj == null)throw new NullPointerException();return obj;
}

这个方法是 Objects 类的一个静态方法, Objects 类是一个 Java 静态类, 里面包含了很多 Java 工具方法, 其方法都是静态方法, 其类的说明文档如下:

/*** This class consists of {@code static} utility methods for operating* on objects.  These utilities include {@code null}-safe or {@code* null}-tolerant methods for computing the hash code of an object,* returning a string for an object, and comparing two objects.** @since 1.7*/
public final class Objects {...
}

可以看出, 这个类还包括了很多关于类操作的使用工具方法, 例如比较两个类是否相等, 计算类的 Hash Code 等方法, 这个类以后有机会进行学习和介绍.

回到 requireNonNull() 这个方法, 其源码实现非常简单, 只是进行了一个简单的判断, 如果所要判断的元素为 null, 则返回空指针异常 NullPointerException, 否则直接返回对应的对象.

这看上去好像是一个多余的操作, 因为如果我们试图去调用一个空对象的方法, 也会抛出 NullPointerException 运行时异常, 那么我们为什么要多此一举进行这样的一次检查呢? 这一问题在 StackOverflow 上有人进行了解答 Why should one use Objects.requireNonNull?.

看了他们的回答, 总结为以下几点:

首先, 从这个方法的名称可以看出, 这个方法使用的场景是, 我们使用一个对象的方法时, 正常的运行状态应该能保证这个对象的引用非空, 如果这个对象为空了, 那一定是其他某个地方出错了, 所以我们应该抛出一个异常, 我们不应该在这里处理这个非空异常.

其次, 这里涉及到一个很重要的编程思想, 就是 Fail-fast 思想, 翻译过来就是, 让错误尽可能早的出现, 不要等到我们很多工作执行到一半之后才抛出异常, 这样很可能使得一部分变量处于异常状态, 出现更多的错误. 这也是 requireNonNull 这个方法的设计思想, 让错误尽早出现. 使用这个方法, 我们明确的抛出异常, 发生错误时, 我们立刻抛出异常.

StackOverflow 中的一个回答举了一个具体的例子来回答这个问题, 例如有下面这样一个类:

public class Dictionary {private final List<String> words;private final LookupService lookupService;public Dictionary(List<String> words) {this.words = this.words;this.lookupService = new LookupService(words);}public boolean isFirstElement(String userData) {return lookupService.isFirstElement(userData);}
}public class LookupService {List<String> words;public LookupService(List<String> words) {this.words = words;}public boolean isFirstElement(String userData) {return words.get(0).contains(userData);}
}

这里, 两个类是包含的关系, 传入的 List 参数没有做非空检查. 如果我们一不小心在 Dictionary 的构造方法中传入了 null, 如下所示:

Dictionary dictionary = new Dictionary(null); // exception thrown lately : only in the next statement
boolean isFirstElement = dictionary.isFirstElement("anyThing");

我们在构造时没有任何异常, 但是当我们调用方法时, 会抛出 NPE:

Exception in thread "main" java.lang.NullPointerExceptionat LookupService.isFirstElement(LookupService.java:5)at Dictionary.isFirstElement(Dictionary.java:15)at Dictionary.main(Dictionary.java:22)

JVM 告诉我们, 在执行 return words.get(0).contains(userData) 这条语句时, 发生了异常, 但是这个异常非常不明确, 从报错信息来看, 有多种可能会导致这个异常发生, 是因为 words 为空, 还是 words.get(0) 为空? 或者两者都为空? 这都是不明确的. 同时, 我们也无法确定是在这两个类的哪个环节出了错, 这些都是不明确的, 给我们程序 debug 造成了很大的困难.

然而, 当我们使用如下方式实现:

public Dictionary(List<String> words) {this.words = Objects.requireNonNull(words);this.lookupService = new LookupService(words);
}

按照这种实现方式, 在我们执行构造方法时, 就会明确抛出错误.

// exception thrown early : in the constructor
Dictionary dictionary = new Dictionary(null);// we never arrive here
boolean isFirstElement = dictionary.isFirstElement("anyThing");
Exception in thread "main" java.lang.NullPointerExceptionat java.util.Objects.requireNonNull(Objects.java:203)at com.Dictionary.(Dictionary.java:15)at com.Dictionary.main(Dictionary.java:24)

这样我们进行 debug 时就明确很多, 少走很多弯路.

除此之外, 这个方法的作用也是一个明确和不明确的区别, 使用这个方法表示我们明确进行了这个判断, 其实与我们自己使用 if-else 进行判断是一样的, 只是这个工具类简化了这样的操作, 让我们的代码看上去更加简洁, 可读性更强.

此外, requireNonNull 方法有一个重载方法, 可以提供一个报错信息, 以供我们 debug 的时候显示. 我们使用这个引用的时候, 应当保证非空, 如果不然, 会抛出异常告诉我们其他地方出错了, 这里出现了空指针异常. 这个方法重载的实现如下:

/*** Checks that the specified object reference is not {@code null} and* throws a customized {@link NullPointerException} if it is. This method* is designed primarily for doing parameter validation in methods and* constructors with multiple parameters, as demonstrated below:* <blockquote><pre>* public Foo(Bar bar, Baz baz) {*     this.bar = Objects.requireNonNull(bar, "bar must not be null");*     this.baz = Objects.requireNonNull(baz, "baz must not be null");* }* </pre></blockquote>** @param obj     the object reference to check for nullity* @param message detail message to be used in the event that a {@code*                NullPointerException} is thrown* @param <T> the type of the reference* @return {@code obj} if not {@code null}* @throws NullPointerException if {@code obj} is {@code null}*/
public static <T> T requireNonNull(T obj, String message) {if (obj == null)throw new NullPointerException(message);return obj;
}

例如, 我们在 Android 中可以按照如下方式使用:

String username = Objects.requireNonNull(textInputLayoutUsername.getEditText(), "TextInputLayout must have an EditText as child").getText().toString();

这是一个从 TextInpuLayout 获取用户输入内容的方法, 通常使用 TextInputLayout 包裹一个 EditText 来接收用户输入, 因此我们需要通过 TextInputLayoutgetEditText() 方法来获取对应的 EditText, 如果我们布局有问题, 则该方法可能返回 null, 因此我们可以通过上述方法, 抛出一个明确异常, 如果运行时出现问题, 我们也可以很快知道是因为我们 TextInputLayout 无法获取 EditText 而出错的.

Objects.requireNonNull 方法说明相关推荐

  1. 深入挖掘为什么要使用Objects.requireNonNull方法

    引入 在一次学习过程中,通过ImageIO.read方法访问本地图片的时候,IDEA给出了Warning并提出了改善建议: //源码为: bullet=ImageIO.read(ResourceMgr ...

  2. Objects.requireNonNull( )方法说明

    Objects.requireNonNull( )方法在java.util.Objects中 作用就是判断一个对象是否为空 底层源码: /* @param obj 需要检测是否为空的对象* @para ...

  3. java requirenonnull_Java null判断新方法:Objects.requireNonNull 你过用吗?

    1.方法介绍 有时候,我们为了使得对象不为空,可以使用Objects.requireNonNull()方法对对象进行判断,方法参数: Objects.requireNonNull(T obj); Ob ...

  4. Java Objects.requireNonNull

    在学习java动态代理,看到Proxy类中Objects.requireNonNull(T)及Objects.requireNonNull(T obj, String message)来判断传入方法的 ...

  5. git pull 卡在 Unpacking objects 解决方法

    git pull 卡在 Unpacking objects 解决方法 在拉取大型二进制对象(如Adobe Illustrator文件等)时,可能会使整个拉取/推送/克隆过程陷入困境. 如果你仓库没有过 ...

  6. python 多关键字匹配_使用django的objects.filter()方法匹配多个关键字的方法

    介绍: 今天在使用django的时候忽然想用到,如何匹配多个关键字的操作,我们知道django有一个objects.filter()方法,我们可以通过如下一句代码实现匹配数据库中title包含key关 ...

  7. python中objects_python之django的objects.get和objects.filter方法

    为了说明它们两者的区别定义2个models class Student(models.Model): name = models.CharField('姓名', max_length=20, defa ...

  8. Python Django 自定义Manager重写objects.create()方法代码示例

  9. Java 8中Collectors.groupingBy方法空指针异常源码分析

    现在有这样的一个需求:老板让把所有的员工按年龄进行分组,然后统计各个年龄的人数. 这个需求,如果是在数据库中,可以直接使用一个 group by 语句进行统计即可,那么在 Java 中的话,可以借助于 ...

最新文章

  1. 程序员面试题精选100题(39)-颠倒栈[数据结构]
  2. python实验八分支语句_python语句(分支,循环)
  3. 2017级软件2班安卓应用开发课程主页
  4. sphinx的配置和管理
  5. 人生不值得,我在用python.1_关于python
  6. iPhone 不能读取plist文件!?
  7. ASP.NET Core部署到CentOS7,使用Nginx代理
  8. Django之Form组件补充
  9. 是德科技N9020A 频谱分析仪技术资料说明
  10. 数列随机分组matlab,MATLAB如何随机分组数据
  11. java bmp透明底色_C++ 设置透明背景图片
  12. PAT 1055 集体照
  13. 回溯法 子集和问题
  14. oracle 数据库模式对象,索引,序列,同义词,查看用户拥有的表,聚簇,数据库链接
  15. VMvare虚拟机删除快照时卡住的解决办法
  16. 什么是top sql
  17. 在python中输入圆的半_极客起源 - geekori.com - 问题详情 - python动态圆更新糅合到地图显示里...
  18. js中的设计模式之中介者模式
  19. python面向过程学习笔记
  20. 「多校联考」第三周二场

热门文章

  1. 嵌入式Linux初始化硬件RTC,嵌入式Linux系统中的快速启动技术研究
  2. ot协议是什么_OT的完整形式是什么?
  3. strictmath_Java StrictMath nextUp()方法与示例
  4. 奥鹏东北大学作业答案计算机网络,东北大学17秋学期《计算机网络》在线作业1参考答案...
  5. java script创建对象_JavaScript七种非常经典的创建对象方式
  6. hive map格式转换为字符串_Hive与MySQL的不同之处之类型转换cast和covert函数
  7. 如何使用JavaScript访问对象的键中有空格的对象?
  8. IRCTC的完整形式是什么?
  9. MySQL 索引失效的 15 种场景!
  10. javascript数组去重方法汇总