null 参数的 IllegalArgumentException 或 NullPointerException?

发布于 2024-07-05 10:44:01 字数 1447 浏览 8 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(26

鱼窥荷 2024-07-12 10:44:02

您应该使用 IllegalArgumentException (IAE),而不是 NullPointerException (NPE),原因如下:

首先,NPE JavaDoc 明确列出了 NPE 合适的情况。 请注意,当 null 使用不当时,所有这些都会由运行时抛出。 相反,IAE JavaDoc 无法更清楚的是:“抛出该异常表示已向方法传递了非法或不适当的参数。” 是的,就是你!

其次,当您在堆栈跟踪中看到 NPE 时,您会假设什么? 可能有人取消引用了 null。 当您看到 IAE 时,您会假设堆栈顶部的方法的调用者传递了非法值。 同样,后一个假设是正确的,前一个假设是误导性的。

第三,由于IAE显然是为了验证参数而设计的,所以你必须假设它是例外的默认选择,那么为什么你会选择NPE呢? 当然不是为了不同的行为——你真的希望调用代码从 IAE 中单独捕获 NPE 并因此做一些不同的事情吗? 您是否想传达更具体的错误消息? 但无论如何,您都可以在异常消息文本中执行此操作,就像处理所有其他不正确的参数一样。

第四,所有其他不正确的参数数据都会是IAE,那为什么不一致呢? 为什么非法 null 如此特殊,值得与所有其他类型的非法参数分开处理?

最后,我接受其他答案给出的论点,即部分 Java API 以这种方式使用 NPE。 然而,Java API 与从异常类型到命名约定的所有内容都不一致,因此我认为只是盲目地复制 Java API(您最喜欢的部分)并不足以推翻这些其他考虑因素。

You should be using IllegalArgumentException (IAE), not NullPointerException (NPE) for the following reasons:

First, the NPE JavaDoc explicitly lists the cases where NPE is appropriate. Notice that all of them are thrown by the runtime when null is used inappropriately. In contrast, the IAE JavaDoc couldn't be more clear: "Thrown to indicate that a method has been passed an illegal or inappropriate argument." Yup, that's you!

Second, when you see an NPE in a stack trace, what do you assume? Probably that someone dereferenced a null. When you see IAE, you assume the caller of the method at the top of the stack passed in an illegal value. Again, the latter assumption is true, the former is misleading.

Third, since IAE is clearly designed for validating parameters, you have to assume it as the default choice of exception, so why would you choose NPE instead? Certainly not for different behavior -- do you really expect calling code to catch NPE's separately from IAE and do something different as a result? Are you trying to communicate a more specific error message? But you can do that in the exception message text anyway, as you should for all other incorrect parameters.

Fourth, all other incorrect parameter data will be IAE, so why not be consistent? Why is it that an illegal null is so special that it deserves a separate exception from all other types of illegal arguments?

Finally, I accept the argument given by other answers that parts of the Java API use NPE in this manner. However, the Java API is inconsistent with everything from exception types to naming conventions, so I think just blindly copying (your favorite part of) the Java API isn't a good enough argument to trump these other considerations.

你的心境我的脸 2024-07-12 10:44:02

如果您不希望 null 成为允许的值,则似乎会调用 IllegalArgumentException ,并且如果您不希望 null 成为允许的值,则会抛出 NullPointerException试图使用一个结果为null的变量。

It seems like an IllegalArgumentException is called for if you don't want null to be an allowed value, and the NullPointerException would be thrown if you were trying to use a variable that turns out to be null.

青衫负雪 2024-07-12 10:44:02

标准是抛出NullPointerException。 一般无误的“Effective Java”在第 42 条(第一版)、第 60 条(第二版)或第 72 条(第三版)“赞成使用标准异常”中对此进行了简要讨论:

“可以说,所有方法都是错误的
调用归结为非法
争论或非法状态,但其他
异常通常用于
某些类型的非法论点和
状态。 如果调用者传入 null
某些参数为空值
被禁止,公约规定
抛出 NullPointerException
而不是 IllegalArgumentException。”

The standard is to throw the NullPointerException. The generally infallible "Effective Java" discusses this briefly in Item 42 (first edition), Item 60 (second edition), or Item 72 (third edition) "Favor the use of standard exceptions":

"Arguably, all erroneous method
invocations boil down to an illegal
argument or illegal state, but other
exceptions are standardly used for
certain kinds of illegal arguments and
states. If a caller passes null in
some parameter for which null values
are prohibited, convention dictates
that NullPointerException be thrown
rather than IllegalArgumentException."

停滞 2024-07-12 10:44:02

我一直赞成对空参数抛出 IllegalArgumentException ,直到今天,当我注意到 Java 7 中的 java.util.Objects.requireNonNull 方法时。使用该方法,相反做:

if (param == null) {
    throw new IllegalArgumentException("param cannot be null.");
}

你可以做:

Objects.requireNonNull(param);

如果你传递的参数是null,它会抛出一个NullPointerException

鉴于该方法正好位于 java.util 的中间,我认为它的存在是一个非常强烈的迹象,表明抛出 NullPointerException 是“Java 的做事方式” 。

我想无论如何我已经决定了。

请注意,有关硬调试的参数是虚假的,因为您当然可以向 NullPointerException 提供一条消息,说明什么是 null 以及为什么它不应该是 null。 就像 IllegalArgumentException 一样。

NullPointerException 的另一个优点是,在高性能关键代码中,您可以省去对 null 的显式检查(以及带有友好错误消息的 NullPointerException),并且只需依赖于在 null 参数上调用方法时自动获得的 NullPointerException。 如果您快速调用一个方法(即快速失败),那么您基本上会获得相同的效果,只是对开发人员来说不太友好。 大多数时候,最好显式检查并抛出一条有用的消息来指示哪个参数为空,但最好 如果性能需要,可以选择更改,而不破坏方法/构造函数的已发布合同。

I was all in favour of throwing IllegalArgumentException for null parameters, until today, when I noticed the java.util.Objects.requireNonNull method in Java 7. With that method, instead of doing:

if (param == null) {
    throw new IllegalArgumentException("param cannot be null.");
}

you can do:

Objects.requireNonNull(param);

and it will throw a NullPointerException if the parameter you pass it is null.

Given that that method is right bang in the middle of java.util I take its existence to be a pretty strong indication that throwing NullPointerException is "the Java way of doing things".

I think I'm decided at any rate.

Note that the arguments about hard debugging are bogus because you can of course provide a message to NullPointerException saying what was null and why it shouldn't be null. Just like with IllegalArgumentException.

One added advantage of NullPointerException is that, in highly performance critical code, you could dispense with an explicit check for null (and a NullPointerException with a friendly error message), and just rely on the NullPointerException you'll get automatically when you call a method on the null parameter. Provided you call a method quickly (i.e. fail fast), then you have essentially the same effect, just not quite as user friendly for the developer. Most times it's probably better to check explicitly and throw with a useful message to indicate which parameter was null, but it's nice to have the option of changing that if performance dictates without breaking the published contract of the method/constructor.

時窥 2024-07-12 10:44:02

我倾向于遵循 JDK 库的设计,尤其是集合和并发(Joshua Bloch、Doug Lea,这些人知道如何设计可靠的 API)。 不管怎样,JDK 中的许多 API 都会主动抛出 NullPointerException。

例如,Map.containsKey 的 Javadoc 指出:

如果键为 null 并且此映射,则@抛出 NullPointerException
不允许空键(可选)。

抛出你自己的 NPE 是完全正确的。 约定是在异常消息中包含为 null 的参数名称。

该模式是:

public void someMethod(Object mustNotBeNull) {  
    if (mustNotBeNull == null) {  
        throw new NullPointerException("mustNotBeNull must not be null");  
    }  
}

无论您做什么,都不允许设置错误的值,并在其他代码尝试使用它时抛出异常。 这使得调试成为一场噩梦。 您应该始终遵循“快速失败”原则。

I tend to follow the design of JDK libraries, especially Collections and Concurrency (Joshua Bloch, Doug Lea, those guys know how to design solid APIs). Anyway, many APIs in the JDK pro-actively throws NullPointerException.

For example, the Javadoc for Map.containsKey states:

@throws NullPointerException if the key is null and this map
does not permit null keys (optional).

It's perfectly valid to throw your own NPE. The convention is to include the parameter name which was null in the message of the exception.

The pattern goes:

public void someMethod(Object mustNotBeNull) {  
    if (mustNotBeNull == null) {  
        throw new NullPointerException("mustNotBeNull must not be null");  
    }  
}

Whatever you do, don't allow a bad value to get set and throw an exception later when other code attempts to use it. That makes debugging a nightmare. You should always the follow the "fail-fast" principle.

乱世争霸 2024-07-12 10:44:02

对杰森·科恩的论点投了赞成票,因为它表达得很好。 让我一步步拆解吧。 ;-)

  • NPE JavaDoc 明确表示,”空对象的其他非法使用”。 如果它仅限于运行时在不应该遇到 null 时遇到 null 的情况,那么所有此类情况都可以定义得更加简洁。

  • 如果你假设错误的事情,那也无济于事,但是假设正确应用了封装,你真的不应该关心或注意 null 是否被不恰当地取消引用,以及方法是否检测到不适当的 null 并引发异常 了

  • 我会选择 NPE 而不是 IAE 出于多种原因

    • 更具体地说明非法运营的性质
    • 错误地允许空值的逻辑往往与错误地允许非法值的逻辑有很大不同。 例如,如果我正在验证用户输入的数据,如果我得到不可接受的值,则该错误的根源在于应用程序的最终用户。 如果我得到一个空值,那就是程序员错误。
    • 无效值可能会导致堆栈溢出、内存不足错误、解析异常等问题。事实上,大多数错误通常在某些时候表现为某些方法调用中的无效值。 出于这个原因,我认为 IAE 实际上是 RuntimeException 下所有异常中最通用的
  • 实际上,其他无效参数可能会导致各种其他异常。 UnknownHostExceptionFileNotFoundException,各种语法错误异常,IndexOutOfBoundsException、认证失败等等

总体感觉NPE之所以饱受诟病,是因为传统上与不遵循快速失败原则的代码相关联。 再加上 JDK 未能用消息字符串填充 NPE,确实造成了一种没有充分根据的强烈负面情绪。 事实上,从运行时的角度来看,NPE 和 IAE 之间的区别严格在于名称。 从这个角度来看,你的名字越准确,你给呼叫者的信息就越清晰。

Voted up Jason Cohen's argument because it was well presented. Let me dismember it step by step. ;-)

  • The NPE JavaDoc explicitly says, "other illegal uses of the null object". If it was just limited to situations where the runtime encounters a null when it shouldn't, all such cases could be defined far more succinctly.

  • Can't help it if you assume the wrong thing, but assuming encapsulation is applied properly, you really shouldn't care or notice whether a null was dereferenced inappropriately vs. whether a method detected an inappropriate null and fired an exception off.

  • I'd choose NPE over IAE for multiple reasons

    • It is more specific about the nature of the illegal operation
    • Logic that mistakenly allows nulls tends to be very different from logic that mistakenly allows illegal values. For example, if I'm validating data entered by a user, if I get value that is unacceptable, the source of that error is with the end user of the application. If I get a null, that's programmer error.
    • Invalid values can cause things like stack overflows, out of memory errors, parsing exceptions, etc. Indeed, most errors generally present, at some point, as an invalid value in some method call. For this reason I see IAE as actually the MOST GENERAL of all exceptions under RuntimeException.
  • Actually, other invalid arguments can result in all kinds of other exceptions. UnknownHostException, FileNotFoundException, a variety of syntax error exceptions, IndexOutOfBoundsException, authentication failures, etc., etc.

In general, I feel NPE is much maligned because traditionally has been associated with code that fails to follow the fail fast principle. That, plus the JDK's failure to populate NPE's with a message string really has created a strong negative sentiment that isn't well founded. Indeed, the difference between NPE and IAE from a runtime perspective is strictly the name. From that perspective, the more precise you are with the name, the more clarity you give to the caller.

毅然前行 2024-07-12 10:44:02

这是一个“圣战”风格的问题。 换句话说,两种选择都不错,但人们会有自己的偏好,并且会誓死捍卫。

It's a "Holy War" style question. In others words, both alternatives are good, but people will have their preferences which they will defend to the death.

仙气飘飘 2024-07-12 10:44:02

如果它是一个 setter 方法,并且将 null 传递给它,我认为抛出 IllegalArgumentException 会更有意义。 在您尝试实际使用 null 的情况下,NullPointerException 似乎更有意义。

因此,如果您正在使用它并且它是 null,则 NullPointer。 如果传入的值是 null,则 IllegalArgument

If it's a setter method and null is being passed to it, I think it would make more sense to throw an IllegalArgumentException. A NullPointerException seems to make more sense in the case where you're attempting to actually use the null.

So, if you're using it and it's null, NullPointer. If it's being passed in and it's null, IllegalArgument.

暖阳 2024-07-12 10:44:02

Apache Commons Lang 有一个 NullArgumentException ,它执行以下操作:这里讨论的事情有很多:它扩展了 IllegalArgumentException ,并且它的唯一构造函数采用本应为非空的参数名称。

虽然我认为抛出 NullArgumentException 或 IllegalArgumentException 之类的内容可以更准确地描述异常情况,但我和我的同事选择遵循 Bloch 关于该主题的建议。

Apache Commons Lang has a NullArgumentException that does a number of the things discussed here: it extends IllegalArgumentException and its sole constructor takes the name of the argument which should have been non-null.

While I feel that throwing something like a NullArgumentException or IllegalArgumentException more accurately describes the exceptional circumstances, my colleagues and I have chosen to defer to Bloch's advice on the subject.

哎呦我呸! 2024-07-12 10:44:02

实际上,在我看来,抛出 IllegalArgumentException 或 NullPointerException 的问题只是少数对 Java 异常处理理解不完整的人的一场“圣战”。 一般来说,规则很简单,如下所示:

  • 必须尽快指示参数约束违规(->快速失败),以避免非法状态,
  • 在无效空指针的情况下,非法 状态更难以调试无论出于何种原因,
  • 如果数组/集合索引非法,则抛出 NullPointerException;如果数组/集合大小为负,则抛出 ArrayIndexOutOfBounds;
  • 则抛出 NegativeArraySizeException
  • 如果上述未涵盖的非法参数,并且您不这样做, 如果有另一种更具体的异常类型,则抛出 IllegalArgumentException 作为废纸篓
  • ,如果字段内发生约束冲突,并且由于某些有效原因无法通过快速失败来避免,则捕获并重新抛出 IllegalStateException 或更具体的检查异常。 在这种情况下,永远不要让原始的 NullPointerException、ArrayIndexOutOfBounds 等传递!

至少有三个非常充分的理由反对将所有类型的参数约束违规映射到 IllegalArgumentException,其中第三个可能非常严重,以至于标志着这种做法的不良风格:

(1)程序员不能安全地假设所有情况违反参数约束会导致 IllegalArgumentException,因为如果没有更具体的可用异常类型,大多数标准类都会使用此异常,而不是作为废纸篓。 尝试将所有违反参数约束的情况映射到 API 中的 IllegalArgumentException 只会导致程序员在使用您的类时感到沮丧,因为标准库大多遵循违反您的规则的不同规则,并且您的大多数 API 用户也会使用它们!

(2) 映射异常实际上会导致由单继承引起的不同类型的异常:所有Java异常都是类,因此仅支持单继承。 因此,没有办法创建一个真正同时存在 NullPointerException 和 IllegalArgumentException 的异常,因为子类只能从其中之一继承。 因此,当程序尝试以编程方式纠正问题时,例如通过将默认值输入到调用重复中,在空参数的情况下抛出 IllegalArgumentException 会使 API 用户更难区分问题!

(3) 映射实际上会产生错误屏蔽的危险:为了将参数约束违规映射到 IllegalArgumentException,您需要在每个具有任何受约束参数的方法中编写一个外部 try-catch。 然而,简单地在此 catch 块中捕获 RuntimeException 是不可能的,因为这存在将您中使用的自由方法抛出的已记录的 RuntimeException 映射到 IllegalArgumentException 的风险,即使它们不是由参数约束违规引起的。 因此,您需要非常具体,但即使这样的努力也无法保护您免受意外将另一个 API 的未记录的运行时异常(即错误)映射到您的 API 的 IllegalArgumentException 的情况。 因此,即使是最仔细的映射也有可能将其他库制造商的编程错误掩盖为方法用户的参数约束违规,这简直是可笑的行为!

另一方面,在标准实践中,规则保持简单,异常原因保持公开且具体。 对于方法调用者来说,规则也很简单:
- 如果由于传递了非法值而遇到任何类型的已记录的运行时异常,请使用默认值重复调用(对于此特定异常是必要的),或者更正您的代码
- 另一方面,如果您遇到未记录给定参数集发生的运行时异常,请向方法的制造者提交错误报告,以确保他们的代码或文档已修复。

Actually, the question of throwing IllegalArgumentException or NullPointerException is in my humble view only a "holy war" for a minority with an incomlete understanding of exception handling in Java. In general, the rules are simple, and as follows:

  • argument constraint violations must be indicated as fast as possible (-> fast fail), in order to avoid illegal states which are much harder to debug
  • in case of an invalid null pointer for whatever reason, throw NullPointerException
  • in case of an illegal array/collection index, throw ArrayIndexOutOfBounds
  • in case of a negative array/collection size, throw NegativeArraySizeException
  • in case of an illegal argument that is not covered by the above, and for which you don't have another more specific exception type, throw IllegalArgumentException as a wastebasket
  • on the other hand, in case of a constraint violation WITHIN A FIELD that could not be avoided by fast fail for some valid reason, catch and rethrow as IllegalStateException or a more specific checked exception. Never let pass the original NullPointerException, ArrayIndexOutOfBounds, etc in this case!

There are at least three very good reasons against the case of mapping all kinds of argument constraint violations to IllegalArgumentException, with the third probably being so severe as to mark the practice bad style:

(1) A programmer cannot a safely assume that all cases of argument constraint violations result in IllegalArgumentException, because the large majority of standard classes use this exception rather as a wastebasket if there is no more specific kind of exception available. Trying to map all cases of argument constraint violations to IllegalArgumentException in your API only leads to programmer frustration using your classes, as the standard libraries mostly follow different rules that violate yours, and most of your API users will use them as well!

(2) Mapping the exceptions actually results in a different kind of anomaly, caused by single inheritance: All Java exceptions are classes, and therefore support single inheritance only. Therefore, there is no way to create an exception that is truly say both a NullPointerException and an IllegalArgumentException, as subclasses can only inherit from one or the other. Throwing an IllegalArgumentException in case of a null argument therefore makes it harder for API users to distinguish between problems whenever a program tries to programmatically correct the problem, for example by feeding default values into a call repeat!

(3) Mapping actually creates the danger of bug masking: In order to map argument constraint violations into IllegalArgumentException, you'll need to code an outer try-catch within every method that has any constrained arguments. However, simply catching RuntimeException in this catch block is out of the question, because that risks mapping documented RuntimeExceptions thrown by libery methods used within yours into IllegalArgumentException, even if they are no caused by argument constraint violations. So you need to be very specific, but even that effort doesn't protect you from the case that you accidentally map an undocumented runtime exception of another API (i.e. a bug) into an IllegalArgumentException of your API. Even the most careful mapping therefore risks masking programming errors of other library makers as argument constraint violations of your method's users, which is simply hillareous behavior!

With the standard practice on the other hand, the rules stay simple, and exception causes stay unmasked and specific. For the method caller, the rules are easy as well:
- if you encounter a documented runtime exception of any kind because you passed an illegal value, either repeat the call with a default (for this specific exceptions are neccessary), or correct your code
- if on the other hand you enccounter a runtime exception that is not documented to happen for a given set of arguments, file a bug report to the method's makers to ensure that either their code or their documentation is fixed.

决绝 2024-07-12 10:44:02

可接受的做法是使用 IllegalArgumentException( String message ) 来声明参数无效并提供尽可能多的详细信息...也就是说,发现参数为 null,而异常为非-null,你会做这样的事情:

if( variable == null )
    throw new IllegalArgumentException("The object 'variable' cannot be null");

你几乎没有理由隐式使用“NullPointerException”。 NullPointerException 是当您尝试在空引用上执行代码时 Java 虚拟机抛出的异常(如 toString())。

The accepted practice if to use the IllegalArgumentException( String message ) to declare a parameter to be invalid and give as much detail as possible... So to say that a parameters was found to be null while exception non-null, you would do something like this:

if( variable == null )
    throw new IllegalArgumentException("The object 'variable' cannot be null");

You have virtually no reason to implicitly use the "NullPointerException". The NullPointerException is an exception thrown by the Java Virtual Machine when you try to execute code on null reference (Like toString()).

书信已泛黄 2024-07-12 10:44:02

作为一个主观问题,这个问题应该被关闭,但因为它仍然是开放的:

这是我以前的工作地点使用的内部政策的一部分,而且效果非常好。 这全是凭记忆,所以我记不清具体的措辞了。 值得注意的是,他们没有使用检查异常,但这超出了问题的范围。 他们使用的未经检查的异常分为 3 个主要类别。

NullPointerException:不要故意抛出。 NPE 仅在取消引用空引用时由 VM 抛出。 应尽一切努力确保这些永远不会被抛出。 @Nullable 和 @NotNull 应与代码分析工具结合使用来查找这些错误。

IllegalArgumentException:当函数的参数不符合公共文档时抛出,这样就可以根据传入的参数来识别和描述错误。OP的情况就属于此类。

IllegalStateException:当调用函数并且其参数在传递时意外或与该方法所属的对象的状态不兼容时抛出。

例如,有两个内部版本的 IndexOutOfBoundsException 用于具有长度的事物。 IllegalStateException 的子类,在索引大于长度时使用。 另一个是 IllegalArgumentException 的子类,在索引为负数时使用。 这是因为您可以向对象添加更多项目,并且参数将有效,而负数则永远无效。

正如我所说,这个系统运行得非常好,并且需要有人来解释为什么存在这种区别:“根据错误的类型,您可以很简单地弄清楚该怎么做。即使您实际上无法弄清楚弄清楚出了什么问题,您就可以找出在哪里捕获该错误并创建额外的调试信息。”

NullPointerException:处理 Null 情况或放入断言,以便不引发 NPE。 如果你放入断言只是其他两种类型之一。 如果可能,继续调试,就好像断言一开始就存在一样。

IllegalArgumentException:您的调用站点出现问题。 如果传入的值来自另一个函数,请找出您收到错误值的原因。 如果您传入参数之一,则传播错误会检查调用堆栈,直到找到未返回预期结果的函数。

IllegalStateException:您没有以正确的顺序调用函数。 如果您正在使用其中一个参数,请检查它们并抛出一个 IllegalArgumentException 来描述问题。 然后,您可以将脸颊向上传播到堆栈上,直到找到问题为止。

不管怎样,他的观点是你只能将 IllegalArgumentAssertions 复制到堆栈上。 您无法将 IllegalStateExceptions 或 NullPointerExceptions 传播到堆栈中,因为它们与您的函数有关。

As a subjective question this should be closed, but as it's still open:

This is part of the internal policy used at my previous place of employment and it worked really well. This is all from memory so I can't remember the exact wording. It's worth noting that they did not use checked exceptions, but that is beyond the scope of the question. The unchecked exceptions they did use fell into 3 main categories.

NullPointerException: Do not throw intentionally. NPEs are to be thrown only by the VM when dereferencing a null reference. All possible effort is to be made to ensure that these are never thrown. @Nullable and @NotNull should be used in conjunction with code analysis tools to find these errors.

IllegalArgumentException: Thrown when an argument to a function does not conform to the public documentation, such that the error can be identified and described in terms of the arguments passed in. The OP's situation would fall into this category.

IllegalStateException: Thrown when a function is called and its arguments are either unexpected at the time they are passed or incompatible with the state of the object the method is a member of.

For example, there were two internal versions of the IndexOutOfBoundsException used in things that had a length. One a sub-class of IllegalStateException, used if the index was larger than the length. The other a subclass of IllegalArgumentException, used if the index was negative. This was because you could add more items to the object and the argument would be valid, while a negative number is never valid.

As I said, this system works really well, and it took someone to explain why the distinction is there: "Depending on the type of error it is quite straightforward for you to figure out what to do. Even if you can't actually figure out what went wrong you can figure out where to catch that error and create additional debugging information."

NullPointerException: Handle the Null case or put in an assertion so that the NPE is not thrown. If you put in an assertion is just one of the other two types. If possible, continue debugging as if the assertion was there in the first place.

IllegalArgumentException: you have something wrong at your call site. If the values being passed in are from another function, find out why you are receiving an incorrect value. If you are passing in one of your arguments propagate the error checks up the call stack until you find the function that is not returning what you expect.

IllegalStateException: You have not called your functions in the correct order. If you are using one of your arguments, check them and throw an IllegalArgumentException describing the issue. You can then propagate the cheeks up against the stack until you find the issue.

Anyway, his point was that you can only copy the IllegalArgumentAssertions up the stack. There is no way for you to propagate the IllegalStateExceptions or NullPointerExceptions up the stack because they had something to do with your function.

往日 2024-07-12 10:44:02

非常同意所说的内容。 早失败,快失败。 非常好的例外口头禅。

关于抛出哪个异常的问题主要取决于个人喜好。 在我看来,IllegalArgumentException 似乎比使用 NPE 更具体,因为它告诉我问题出在我传递给该方法的参数上,而不是在执行该方法时可能生成的值上。

我的2美分

Couldn't agree more with what's being said. Fail early, fail fast. Pretty good Exception mantra.

The question about which Exception to throw is mostly a matter of personal taste. In my mind IllegalArgumentException seems more specific than using a NPE since it's telling me that the problem was with an argument I passed to the method and not with a value that may have been generated while performing the method.

My 2 Cents

她比我温柔 2024-07-12 10:44:02

引发 null 参数独有的异常(无论是 NullPointerException 还是自定义类型)可以使自动 null 测试更加可靠。 这种自动化测试可以通过反射和一组默认值来完成,如 Guava 中所示的 NullPointerTester。 例如,NullPointerTester 将尝试调用以下方法...

Foo(String string, List<?> list) {
  checkArgument(string.length() > 0);
  // missing null check for list!
  this.string = string;
  this.list = list;
}

...使用两个参数列表:"", nullnull, ImmutableList.of ()。 它将测试每个调用是否抛出预期的 NullPointerException。 对于此实现,传递 null 列表不会产生 NullPointerException。 但是,它确实会产生 IllegalArgumentException,因为 NullPointerTester 碰巧使用默认字符串 ""。 如果 NullPointerTester 只期望 NullPointerExceptionnull 值,它就会捕获该错误。 如果它期望 IllegalArgumentException,它就会错过它。

Throwing an exception that's exclusive to null arguments (whether NullPointerException or a custom type) makes automated null testing more reliable. This automated testing can be done with reflection and a set of default values, as in Guava's NullPointerTester. For example, NullPointerTester would attempt to call the following method...

Foo(String string, List<?> list) {
  checkArgument(string.length() > 0);
  // missing null check for list!
  this.string = string;
  this.list = list;
}

...with two lists of arguments: "", null and null, ImmutableList.of(). It would test that each of these calls throws the expected NullPointerException. For this implementation, passing a null list does not produce NullPointerException. It does, however, happen to produce an IllegalArgumentException because NullPointerTester happens to use a default string of "". If NullPointerTester expects only NullPointerException for null values, it catches the bug. If it expects IllegalArgumentException, it misses it.

牛↙奶布丁 2024-07-12 10:44:02

尝试使用当前值为 null 的引用变量访问对象时抛出 NullPointerException

当方法接收到的参数格式与方法期望的格式不同时,会抛出IllegalArgumentException

NullPointerException thrown when attempting to access an object with a reference variable whose current value is null.

IllegalArgumentException thrown when a method receives an argument formatted differently than the method expects.

暗地喜欢 2024-07-12 10:44:02

某些集合假设使用 NullPointerException 而不是 IllegalArgumentException 拒绝 null。 例如,如果将包含 null 的集合与拒绝 null 的集合进行比较,第一个集合将调用另一个集合的 containsAll 并捕获其NullPointerException——但不是IllegalArgumentException。 (我正在研究 AbstractSet.equals 的实现。)

您可以合理地认为以这种方式使用未经检查的异常是一种反模式,即将包含 null 的集合与不能包含 null 的集合是一个可能的错误,实际上应该产生异常,或者将 null 放入集合中根本就是一个错误馊主意。 尽管如此,除非您愿意说在这种情况下 equals 应该抛出异常,否则您会一直记住 NullPointerException 在某些情况下是必需的,但在其他情况下则不需要。 (“IAE 在 NPE 之前,除了在 'c' 之后...”)

类似地,构建工具可能会自动插入空检查。 值得注意的是,Kotlin 的编译器在传递时会执行此操作 Java API 的可能为空值。 当检查失败时,结果是 NullPointerException。 因此,要为您拥有的任何 Kotlin 用户和 Java 用户提供一致的行为,您需要使用 NullPointerException

Some collections assume that null is rejected using NullPointerException rather than IllegalArgumentException. For example, if you compare a set containing null to a set that rejects null, the first set will call containsAll on the other and catch its NullPointerException -- but not IllegalArgumentException. (I'm looking at the implementation of AbstractSet.equals.)

You could reasonably argue that using unchecked exceptions in this way is an antipattern, that comparing collections that contain null to collections that can't contain null is a likely bug that really should produce an exception, or that putting null in a collection at all is a bad idea. Nevertheless, unless you're willing to say that equals should throw an exception in such a case, you're stuck remembering that NullPointerException is required in certain circumstances but not in others. ("IAE before NPE except after 'c'...")

Somewhat similarly, build tools may insert null checks automatically. Notably, Kotlin's compiler does this when passing a possibly null value to a Java API. And when a check fails, the result is a NullPointerException. So, to give consistent behavior to any Kotlin users and Java users that you have, you'd need to use NullPointerException.

失去的东西太少 2024-07-12 10:44:02

我想从其他非法参数中挑选出 Null 参数,因此我从 IAE 派生了一个名为 NullArgumentException 的异常。 甚至不需要读取异常消息,我就知道一个空参数被传递到一个方法中,通过读取该消息,我可以找出哪个参数为空。 我仍然使用 IAE 处理程序捕获 NullArgumentException,但在我的日志中我可以快速看到差异。

I wanted to single out Null arguments from other illegal arguments, so I derived an exception from IAE named NullArgumentException. Without even needing to read the exception message, I know that a null argument was passed into a method and by reading the message, I find out which argument was null. I still catch the NullArgumentException with an IAE handler, but in my logs is where I can see the difference quickly.

陈年往事 2024-07-12 10:44:02

一般来说,开发人员应该永远抛出 NullPointerException。 当代码尝试取消引用值为 null 的变量时,运行时会引发此异常。 因此,如果您的方法想要显式禁止 null,而不是恰好有 null 值引发 NullPointerException,则应该抛出 IllegalArgumentException。

In general, a developer should never throw a NullPointerException. This exception is thrown by the runtime when code attempts to dereference a variable who's value is null. Therefore, if your method wants to explicitly disallow null, as opposed to just happening to have a null value raise a NullPointerException, you should throw an IllegalArgumentException.

半步萧音过轻尘 2024-07-12 10:44:02

您应该抛出 IllegalArgumentException,因为这会让程序员明显地知道他做了一些无效的事情。 开发人员已经习惯了看到虚拟机抛出 NPE,以至于任何程序员都不会立即意识到自己的错误,而是会开始随机环顾四周,或者更糟糕的是,指责您的代码存在“错误”。

You should throw an IllegalArgumentException, as it will make it obvious to the programmer that he has done something invalid. Developers are so used to seeing NPE thrown by the VM, that any programmer would not immediately realize his error, and would start looking around randomly, or worse, blame your code for being 'buggy'.

月下伊人醉 2024-07-12 10:44:02

根据您的情况,IllegalArgumentException 是最佳选择,因为 null 不是您的属性的有效值。

According to your scenario, IllegalArgumentException is the best pick, because null is not a valid value for your property.

╰つ倒转 2024-07-12 10:44:02

上述两个例外的链接的定义是
IllegalArgumentException:抛出该异常表示向方法传递了非法或不适当的参数。
NullPointerException:当应用程序在需要对象的情况下尝试使用 null 时抛出。

这里最大的区别是在检查方法的参数是否有效时应该使用 IllegalArgumentException。 每当对象为 null 时被“使用”时,就应该使用 NullPointerException。

我希望这有助于正确看待两者。

The definitions from the links to the two exceptions above are
IllegalArgumentException: Thrown to indicate that a method has been passed an illegal or inappropriate argument.
NullPointerException: Thrown when an application attempts to use null in a case where an object is required.

The big difference here is the IllegalArgumentException is supposed to be used when checking that an argument to a method is valid. NullPointerException is supposed to be used whenever an object being "used" when it is null.

I hope that helps put the two in perspective.

客…行舟 2024-07-12 10:44:02

如果它是一个“setter”,或者我要让成员稍后使用的某个地方,我倾向于使用 IllegalArgumentException。

如果我现在要在方法中使用(取消引用)它,我会主动抛出 NullPointerException。 与让运行时执行此操作相比,我更喜欢这样做,因为我可以提供有用的消息(似乎运行时也可以执行此操作,但这是另一天的咆哮)。

如果我要重写一个方法,我会使用被重写方法使用的任何内容。

If it's a "setter", or somewhere I'm getting a member to use later, I tend to use IllegalArgumentException.

If it's something I'm going to use (dereference) right now in the method, I throw a NullPointerException proactively. I like this better than letting the runtime do it, because I can provide a helpful message (seems like the runtime could do this too, but that's a rant for another day).

If I'm overriding a method, I use whatever the overridden method uses.

放我走吧 2024-07-12 10:44:02

二分法...它们不重叠吗? 只有整体中不重叠的部分才能形成二分法。 照我看来:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));

the dichotomy... Are they non-overlapping? Only non-overlapping parts of a whole can make a dichotomy. As i see it:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));
[旋木] 2024-07-12 10:44:02

在这种情况下,IllegalArgumentException 向使用 API 的用户传达“不应为空”的明确信息。 正如其他论坛用户指出的那样,只要您使用 API 向用户传达正确的信息,您就可以使用 NPE。

GaryF 和tweakt 放弃了推荐使用NPE 的“Effective Java”(我发誓)参考文献。 查看其他优秀 API 的构建方式是了解如何构建您的 API 的最佳方式。

另一个很好的例子是查看 Spring API。 例如, org.springframework.beans.BeanUtils.instantiateClass(Constructor ctor, Object[] args) 有一个 Assert.notNull(ctor, "Constructor must not be null") 行。 org.springframework.util.Assert.notNull(Object object, String message) 方法检查传入的参数(对象)是否为 null,如果是,则抛出一个新的 IllegalArgumentException(message),然后在 org. springframework.beans.BeanUtils.instantiateClass(...) 方法。

In this case, IllegalArgumentException conveys clear information to the user using your API that the " should not be null". As other forum users pointed out you could use NPE if you want to as long as you convey the right information to the user using your API.

GaryF and tweakt dropped "Effective Java" (which I swear by) references which recommends using NPE. And looking at how other good APIs are constructed is the best way to see how to construct your API.

Another good example is to look at the Spring APIs. For example, org.springframework.beans.BeanUtils.instantiateClass(Constructor ctor, Object[] args) has a Assert.notNull(ctor, "Constructor must not be null") line. org.springframework.util.Assert.notNull(Object object, String message) method checks to see if the argument (object) passed in is null and if it is it throws a new IllegalArgumentException(message) which is then caught in the org.springframework.beans.BeanUtils.instantiateClass(...) method.

浸婚纱 2024-07-12 10:44:02

理想情况下,不应引发运行时异常。 应为您的场景创建检查异常(业务异常)。 因为如果抛出并记录这些异常中的任何一个,它会在浏览日志时误导开发人员。 相反,业务异常不会造成恐慌,并且在对日志进行故障排除时通常会被忽略。

Ideally runtime exceptions should not be thrown. A checked exception(business exception) should be created for your scenario. Because if either of these exception is thrown and logged, it misguides the developer while going through the logs. Instead business exceptions do not create that panic and usually ignored while troubleshooting logs.

无敌元气妹 2024-07-12 10:44:02

如果您选择抛出 NPE 并且在方法中使用参数,则显式检查 null 可能是多余且昂贵的。 我认为虚拟机已经为你做到了这一点。

If you choose to throw a NPE and you are using the argument in your method, it might be redundant and expensive to explicitly check for a null. I think the VM already does that for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文