当前位置:网站首页>Object. RequireNonNull method
Object. RequireNonNull method
2022-08-04 06:32:00 【Louzen】
转载:Mlya 的博客
Object.requireNonNull源码:
/** * 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 运行时异常, 那么我们为什么要多此一举进行这样的一次检查呢?
首先, 从这个方法的名称可以看出, 这个方法使用的场景是, 我们使用一个对象的方法时, 正常的运行状态应该能保证这个对象的引用非空, 如果这个对象为空了, 那一定是其他某个地方出错了, 所以我们应该抛出一个异常, 我们不应该在这里处理这个非空异常.
其次, 这里涉及到一个很重要的编程思想, 就是 Fail-fast 思想, 翻译过来就是, 让错误尽可能早的出现, 不要等到我们很多工作执行到一半之后才抛出异常, 这样很可能使得一部分变量处于异常状态, 出现更多的错误. 这也是 requireNonNull 这个方法的设计思想, 让错误尽早出现. 使用这个方法, 我们明确的抛出异常, 发生错误时, 我们立刻抛出异常.
Give a concrete example to answer this question, 例如有下面这样一个类:
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<String> 参数没有做非空检查. 如果我们一不小心在 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.NullPointerException
at 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.NullPointerException
at 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 而出错的.
边栏推荐
- 机器学习——分类问题对于文字标签的处理(特征工程)
- Brief description of database and common operation guide
- 【Copy攻城狮日志】飞浆学院强化学习7日打卡营-学习笔记
- Copy Siege Lion's Annual "Battle" | Review 2020
- [English learning][sentence] good sentence
- MNIST Handwritten Digit Recognition - From Perceptrons to Convolutional Neural Networks
- 线性表之动态数组(ArrayList)的自实现
- (Navigation page) OpenStack-M version - manual construction of two nodes - with video from station B
- MOOSE平台使用入门攻略——如何运行官方教程的例子
- The Unity of ML - agents interpret parameter Settings
猜你喜欢
随机推荐
(导航页)OpenStack-M版-双节点手工搭建-附B站视频
[daily office][ssh]cheatsheet
MNIST手写数字识别 —— 图像分析法实现二分类
ideal life
亚马逊云科技Build On-Amazon Neptune基于知识图谱的推荐模型构建心得
MOOSE平台官方第二个例子分析——关于创建Kernel,求解对流扩散方程
MNIST手写数字识别 —— 基于Mindspore快速构建感知机实现十分类
Object.requireNonNull 方法说明
第一章 绪论
Copy攻城狮的年度之“战”|回顾2020
C语言结构体(必须掌握版)
C语言无符号整型运算
机器学习——分类问题对于文字标签的处理(特征工程)
(Navigation page) OpenStack-M version - manual construction of two nodes - with video from station B
[Deep Learning Diary] Day 1: Hello world, Hello CNN MNIST
Miscellaneous [development] [VS Code] remote - SSD retry failed
MNIST Handwritten Digit Recognition - Building a Perceptron from Zero for Two-Classification
C语言数组的深度分析
LeetCode_Nov_4th_Week
Completely remove MySQL tutorial