Objects.requireNonNull 方法说明
在写代码的时候,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
来接收用户输入, 因此我们需要通过 TextInputLayout
的 getEditText()
方法来获取对应的 EditText
, 如果我们布局有问题, 则该方法可能返回 null
, 因此我们可以通过上述方法, 抛出一个明确异常, 如果运行时出现问题, 我们也可以很快知道是因为我们 TextInputLayout
无法获取 EditText
而出错的.
Objects.requireNonNull 方法说明相关推荐
- 深入挖掘为什么要使用Objects.requireNonNull方法
引入 在一次学习过程中,通过ImageIO.read方法访问本地图片的时候,IDEA给出了Warning并提出了改善建议: //源码为: bullet=ImageIO.read(ResourceMgr ...
- Objects.requireNonNull( )方法说明
Objects.requireNonNull( )方法在java.util.Objects中 作用就是判断一个对象是否为空 底层源码: /* @param obj 需要检测是否为空的对象* @para ...
- java requirenonnull_Java null判断新方法:Objects.requireNonNull 你过用吗?
1.方法介绍 有时候,我们为了使得对象不为空,可以使用Objects.requireNonNull()方法对对象进行判断,方法参数: Objects.requireNonNull(T obj); Ob ...
- Java Objects.requireNonNull
在学习java动态代理,看到Proxy类中Objects.requireNonNull(T)及Objects.requireNonNull(T obj, String message)来判断传入方法的 ...
- git pull 卡在 Unpacking objects 解决方法
git pull 卡在 Unpacking objects 解决方法 在拉取大型二进制对象(如Adobe Illustrator文件等)时,可能会使整个拉取/推送/克隆过程陷入困境. 如果你仓库没有过 ...
- python 多关键字匹配_使用django的objects.filter()方法匹配多个关键字的方法
介绍: 今天在使用django的时候忽然想用到,如何匹配多个关键字的操作,我们知道django有一个objects.filter()方法,我们可以通过如下一句代码实现匹配数据库中title包含key关 ...
- python中objects_python之django的objects.get和objects.filter方法
为了说明它们两者的区别定义2个models class Student(models.Model): name = models.CharField('姓名', max_length=20, defa ...
- Python Django 自定义Manager重写objects.create()方法代码示例
- Java 8中Collectors.groupingBy方法空指针异常源码分析
现在有这样的一个需求:老板让把所有的员工按年龄进行分组,然后统计各个年龄的人数. 这个需求,如果是在数据库中,可以直接使用一个 group by 语句进行统计即可,那么在 Java 中的话,可以借助于 ...
最新文章
- 程序员面试题精选100题(39)-颠倒栈[数据结构]
- python实验八分支语句_python语句(分支,循环)
- 2017级软件2班安卓应用开发课程主页
- sphinx的配置和管理
- 人生不值得,我在用python.1_关于python
- iPhone 不能读取plist文件!?
- ASP.NET Core部署到CentOS7,使用Nginx代理
- Django之Form组件补充
- 是德科技N9020A 频谱分析仪技术资料说明
- 数列随机分组matlab,MATLAB如何随机分组数据
- java bmp透明底色_C++ 设置透明背景图片
- PAT 1055 集体照
- 回溯法 子集和问题
- oracle 数据库模式对象,索引,序列,同义词,查看用户拥有的表,聚簇,数据库链接
- VMvare虚拟机删除快照时卡住的解决办法
- 什么是top sql
- 在python中输入圆的半_极客起源 - geekori.com - 问题详情 - python动态圆更新糅合到地图显示里...
- js中的设计模式之中介者模式
- python面向过程学习笔记
- 「多校联考」第三周二场
热门文章
- 嵌入式Linux初始化硬件RTC,嵌入式Linux系统中的快速启动技术研究
- ot协议是什么_OT的完整形式是什么?
- strictmath_Java StrictMath nextUp()方法与示例
- 奥鹏东北大学作业答案计算机网络,东北大学17秋学期《计算机网络》在线作业1参考答案...
- java script创建对象_JavaScript七种非常经典的创建对象方式
- hive map格式转换为字符串_Hive与MySQL的不同之处之类型转换cast和covert函数
- 如何使用JavaScript访问对象的键中有空格的对象?
- IRCTC的完整形式是什么?
- MySQL 索引失效的 15 种场景!
- javascript数组去重方法汇总