1. Introduction
1.绪论
Among the decisions we make as we’re writing our applications, many are about when to throw exceptions and which type to throw.
在我们编写应用程序时做出的决定中,有许多是关于何时抛出异常以及抛出哪种类型的。
In this quick tutorial, we’re going to tackle the issue of which exception to throw when someone passes a null parameter to one of our methods: IllegalArgumentException or NullPointerException.
在这个快速教程中,我们要解决的问题是,当有人向我们的某个方法传递null参数时,应该抛出哪个异常。IllegalArgumentException或NullPointerException。
We’ll explore the topic by examining the arguments for both sides.
我们将通过研究双方的论点来探讨这个话题。
2. IllegalArgumentException
2.IllegalArgumentException
First, let’s look at the arguments for throwing an IllegalArgumentException.
首先,让我们看看抛出IllegalArgumentException的论据。
Let’s create a simple method that throws an IllegalArgumentException when passed a null:
让我们创建一个简单的方法,当传递一个null时抛出一个IllegalArgumentException。
public void processSomethingNotNull(Object myParameter) {
if (myParameter == null) {
throw new IllegalArgumentException("Parameter 'myParameter' cannot be null");
}
}
Now, let’s move onto the arguments in favor of IllegalArgumentException.
现在,让我们来谈谈支持IllegalArgumentException的论点。
2.1. It’s How the Javadoc Says to Use It
2.1.这是Javadoc说的使用方法
When we read the Javadoc for IllegalArgumentException, it says it’s for use when an illegal or inappropriate value is passed to a method. We can consider a null object to be illegal or inappropriate if our method isn’t expecting it, and this would be an appropriate exception for us to throw.
当我们阅读IllegalArgumentException的Javadoc时,它说当一个非法或不适当的值被传递给一个方法时使用。如果我们的方法不期待一个null对象,我们可以认为它是非法的或不合适的,这将是一个适合我们抛出的异常。
2.2. It Matches Developer Expectations
2.2.它符合开发者的期望
Next, let’s think about how we, as developers, think when we see stack traces in our applications. A very common scenario in which we receive a NullPointerException is when we’ve accidentally tried to access a null object. In this case, we’re going to go as deep into the stack as we can to see what we’re referencing that’s null.
接下来,让我们思考一下,当我们在应用程序中看到堆栈跟踪时,作为开发者的我们是如何思考的。我们收到NullPointerException的一个非常常见的情况是,我们意外地试图访问一个null对象。在这种情况下,我们要尽可能地深入堆栈,看看我们引用的是什么null。
When we get an IllegalArgumentException, we are likely to assume that we’re passing something wrong to a method. In this case, we’ll look in the stack for the bottom-most method we’re calling and start our debugging from there. If we consider this way of thinking, the IllegalArgumentException is going to get us into our stack closer to where the mistake is being made.
当我们得到一个IllegalArgumentException时,我们很可能会认为我们向某个方法传递了错误的东西。在这种情况下,我们会在堆栈中寻找我们正在调用的最底层的方法,并从那里开始我们的调试工作。如果我们考虑这种思维方式,IllegalArgumentException会让我们进入堆栈,更接近错误发生的地方。
2.3. Other Arguments
2.3.其他论据
Before we move onto the arguments for NullPointerException, let’s look at a couple of smaller points in favor of IllegalArgumentException. Some developers feel that only the JDK should be throwing NullPointerException. As we’ll see in the next section, the Javadoc doesn’t support this theory. Another argument is that it’s more consistent to use IllegalArgumentException since that’s what we’d use for other illegal parameter values.
在我们讨论支持NullPointerException的论点之前,让我们看看支持IllegalArgumentException的几个小观点。一些开发者认为,只有JDK应该抛出NullPointerException。正如我们将在下一节看到的,Javadoc并不支持这一理论。另一种说法是,使用IllegalArgumentException更一致,因为我们对其他非法参数值也会使用这种方法。
3. NullPointerException
3.NullPointerException
Next, let’s consider the arguments for NullPointerException.
接下来,让我们考虑一下NullPointerException的论据。
Let’s create an example that throws a NullPointerException:
让我们创建一个抛出NullPointerException的例子。
public void processSomethingElseNotNull(Object myParameter) {
if (myParameter == null) {
throw new NullPointerException("Parameter 'myParameter' cannot be null");
}
}
3.1. It’s How the Javadoc Says to Use It
3.1.这是Javadoc说的使用方法
According to the Javadoc for NullPointerException, NullPointerException is meant to be used for attempting to use null where an object is required. If our method parameter isn’t intended to be null, then we could reasonably consider this as an object being required and throw the NullPointerException.
根据NullPointerException的Javadoc,NullPointerException是用来尝试在需要对象的地方使用null的。如果我们的方法参数不打算是null,那么我们可以合理地认为这是一个对象被要求,并抛出NullPointerException。
3.2. It’s Consistent with JDK APIs
3.2.它与JDK APIs一致
Let’s take a moment to think about many of the common JDK methods we call during development. Many of them throw a NullPointerException if we provide a null. Additionally, Objects.requireNonNull() throws a NullPointerException if we pass in null. According to the Objects documentation, it exists mostly for validating parameters.
让我们花点时间来思考一下我们在开发过程中调用的许多常见的JDK方法。如果我们提供了一个null,它们中的许多都会抛出一个NullPointerException。此外,Objects.requireNonNull() 如果我们传入null,就会抛出NullPointerException 。根据Objects文档,它主要为验证参数而存在。
In addition to JDK methods that throw NullPointerException, we can find other examples of specific exception types being thrown from methods in the Collections API. ArrayList.addAll(index, Collection) throws an IndexOutOfBoundsException if the index is outside of the list size and throws a NullPointerException if the collection is null. These are two very specific exception types rather than the more generic IllegalArgumentException.
除了抛出NullPointerException的JDK方法外,我们还可以找到从集合API中的方法抛出特定异常类型的其他例子。ArrayList.addAll(index, Collection)如果索引超出了列表的大小,会抛出IndexOutOfBoundsException,如果集合是null,会抛出NullPointerException。这是两种非常特殊的异常类型,而不是更通用的IllegalArgumentException。
We could consider IllegalArgumentException to be meant for cases when we don’t have a more specific exception type available to us.
我们可以认为IllegalArgumentException是针对我们没有更具体的异常类型时的情况。
4. Conclusion
4.总结
As we’ve seen in this tutorial, this is a question that doesn’t have a clear answer. The documentation for the two exceptions seems to overlap in that when taken alone, they both sound appropriate. There are also additional compelling arguments for both sides based on how developers do their debugging and on patterns seen in the JDK methods themselves.
正如我们在本教程中看到的,这是一个没有明确答案的问题。两种例外情况的文档似乎有重叠之处,单独来看,它们听起来都很合适。根据开发者如何进行调试以及在JDK方法本身中看到的模式,双方还有一些令人信服的论据。
Whichever exception we chose, we should be consistent throughout our application. Additionally, we can make our exceptions more useful by providing meaningful information to the exception constructor. For example, our applications will be easier to debug if we provide the parameter name in the exception message.
无论我们选择哪种异常,我们都应该在整个应用中保持一致。此外,我们可以通过向异常构造函数提供有意义的信息来使我们的异常更加有用。例如,如果我们在异常信息中提供参数名称,我们的应用程序将更容易调试。
As always, the example code is available over on GitHub.
像往常一样,示例代码可在GitHub上获得。