是否为空参数提供IllegalArgumentException或NullPointerException?[关闭]


547

我有一个简单的属性设置方法,null不适用于此特定属性。在这种情况下,我一直很痛苦:我应该扔IllegalArgumentException还是NullPointerException?从javadocs来看,两者似乎都合适。有某种可以理解的标准吗?还是这只是您应该做的任何事情之一,而且两者都是正确的?

Answers:


299

IllegalArgumentException如果您不想null成为允许的值,则似乎需要调用;如果您NullPointerException尝试使用原来是的变量,则会抛出null


33
对这个问题的以下回答使人信服地认为NullPointerException是正确的异常:stackoverflow.com/a/8160/372926 ; stackoverflow.com/a/8196334/372926 ; 和stackoverflow.com/a/6358/372926
SamStephens 2014年

2
IllegalArgumentException与Java的Objects.requireNonNull(T)和Guava的Preconditions.checkNotNull(T)矛盾,后者抛出NullPointerException。但是,如Jason Cohen出色的答案及其评论部分所述,正确的答案肯定 IllegalArgumentException正确
matoni

417

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

首先,NPE JavaDoc明确列出了适用NPE的情况。请注意,如果使用不当,它们都会被运行时抛出null。相比之下,IAE JavaDoc并不清楚:“抛出该错误以表明方法已传递了非法或不适当的参数。” 是的,就是你!

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

第三,由于IAE显然是为验证参数而设计的,因此您必须将其视为默认的例外选择,那么为什么要选择NPE呢?当然不是出于不同的行为-您是否真的希望调用代码将IPE与IAE分开捕获NPE并因此而有所不同?您是否要传达更具体的错误消息?但是无论如何,您都可以在异常消息文本中执行此操作,就像对所有其他不正确的参数一样。

第四,所有其他不正确的参数数据将是IAE,那么为什么不一致?为什么非法行为null如此特殊,以至于它应与所有其他类型的非法论点分开单独对待?

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


119
有效的Java 2nd Edition,项目60:“可以说,所有错误的方法调用都归结为非法参数或非法状态,但是其他异常通常用于某些非法参数和状态。如果调用方在某些参数中传递null惯例,空值是被禁止的,而不是IllegalArgumentException,它是抛出NullPointerException的。类似地,如果调用者在表示序列索引的参数中传递了超出范围的值,则应该抛出IndexOutOfBoundsException而不是IllegalArgumentException。
吉利2010年

33
NPE的JavaDoc还声明以下内容:“应用程序应抛出此类的实例,以指示对null对象的其他非法使用。” 这可能更清楚:(
R. Martinho Fernandes

12
不幸的是,验证方法Validate.notNull(通用lang)和Preconditions.checkNotNull(番石榴)都抛出NPE :-(
Aaron Digulla 2012年

2
尽管番石榴还具有Preconditions.checkArgument()引发IllegalArgumentException ...
michaelok 2013年

16
来自Guava文档的@AaronDigulla:“我们意识到,有很多有效的参数支持将IAE放在空参数上。实际上,如果我们的时间机器可以追溯到15年以上,我们甚至可以尝试将其推入但是,我们还是决定坚持使用JDK和Effective Java偏好的NullPointerException。如果您坚信IAE是正确的,那么您仍然可以使用checkArgument(arg != null),只是没有返回arg的便利,或者您可以创建您的项目的本地实用程序。” code.google.com/p/guava-libraries/wiki/IdeaGraveyard
Arto Bendiken 2014年

162

标准是扔NullPointerException。通常可靠的“有效Java”在项目42(第一版),项目60(第二版)或项目72(第三版)“优先使用标准异常”中对此进行了简要讨论:

“可以说,所有错误的方法调用都可以归结为非法参数或非法状态,但是对于某些类型的非法参数和状态,通常会使用其他例外。如果调用者在某些参数中传递了null,则禁止使用null值,惯例规定:会抛出NullPointerException而不是IllegalArgumentException。”


95
我非常不同意。仅当JVM意外遵循空引用时,才应引发NullPointerExceptions。那就是当您在凌晨3点被调用以查看代码时的区别。
托尔比约恩Ravn的安徒生

26
我不一定同意该标准(我实际上可以在这个问题上采取任何一种方式),但这就是整个JDK的标准用法,因此,有效的Java为其提供了理由。我认为这是选择是否遵循标准或做您认为正确的事情的情况。除非您有很好的理由(当然这可能符合条件),否则最好遵循标准做法。
GaryF

21
异常跟踪显示了异常的要点,因此,如果异常类型上的差异导致您陷入困境,或者是“可以帮助您的差异”,那么您所做的事情非常错误。
2013年

8
幻想和诡辩。在下面,MB写道:“请注意有关硬调试的参数是虚假的,因为您当然可以向NullPointerException提供一条消息,说明什么是null以及为什么它不应该为null。就像IllegalArgumentException一样。”
吉姆·巴尔特

10
作为这里的原始答复者,让我说这没什么大不了的。当然,不需要进行6年的交谈。随便选一个,并保持一致。正如我指出的那样,标准是NPE。如果出于任何原因您更喜欢IAE,请继续。保持一致。
GaryF

138

IllegalArgumentException直到今天,当我注意到java.util.Objects.requireNonNullJava 7中的方法时,我都支持抛出null参数。使用该方法,而不是这样做:

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

你可以做:

Objects.requireNonNull(param);

NullPointerException如果您传递的参数是,它将抛出a null

鉴于该方法在java.util我中间是正确的,我认为它的存在非常有力地表明抛出NullPointerException是“ Java的处理方式”。

我想我已经决定了。

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

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


14
番石榴Preconditions.checkNotNull(arg)还抛出NPE。
assylias 2012年

14
对于非法的null ARGUMENTS,这实际上并没有增加NullPointerException的权重。JDK requireNonNull()和Guava checkNotNull()都可以在代码中的任何位置使用任何对象调用。例如,您可以在循环内调用它们。requireNotNull()和checkNotNull()可能无法假定被某些方法参数调用并抛出IllegalArgumentException。注意,番石榴还具有Preconditions.checkArgument(),它确实抛出IllegalArgumentException。
Bogdan Calmac

2
Bogdan的观点是合理的,尽管我怀疑requireNonNull的典型(通常是预期用途)用于参数检查。如果您需要检查循环中是否存在非零值,我会认为断言是典型的方式。
MB。

15
我认为Object.requireNonNull()的JavaDoc为参数增加了权重:“此方法主要用于在方法和构造函数中进行参数验证”
Richard Zschech 2015年

请记住,支持隐式空检查的性能参数通常是无效的。JIT能够识别用户无效检查并消除以下隐含的无效检查,和/或对两种无效检查类型使用相同的优化集。有关更多信息,请参见此Wiki,尤其是:用户编写的空检查在大多数情况下在功能上与JVM插入的空检查相同。当然,如果您在自定义消息中做一些更奇怪的事情,则此优化可能不适用。
BeeOnRope '16

70

我倾向于遵循JDK库的设计,尤其是Collections和Concurrency(Joshua Bloch,Doug Lea,那些人知道如何设计可靠的API)。无论如何,JDK中的许多API都会主动抛出NullPointerException

例如,用于Map.containsKey状态的Javadoc :

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

抛出自己的NPE是完全有效的。约定将在异常消息中包含为空的参数名称。

模式如下:

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

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


3
值得深思:也许NullPointerException不扩展IllegalArgumentException的原因是前者可以在不涉及方法参数的情况下发生。
吉利2010年

2
@吉利:也许这个问题首先存在,因为Java不支持多重继承。如果Java支持MI,则可以引发从IllegalArgumentException和NullPointerException继承的异常。
Lie Ryan

7
该消息不需要包含参数,因为它将始终为null,给出:“ null不能为null”,不是很有用。:-)否则,我同意,您可以制作一个“有意义的” NPE,并提供有意义的信息。
PhiLho

5
我必须同意-如有疑问,请遵循标准API。并不是您会想到API中的所有内容都是最佳选择,但是它仍然由数百名开发人员维护和迭代,并被数百万程序员使用。现在在Java 7中,我们还有另一个以这种方式使用NPE的示例。Objects.requireNonNull(T obj)方法-明确指定用于检查对象引用是否为非空,明确指定用于在方法/构造函数中进行参数验证,明确指定如果对象为null则抛出NPE。结束
flamming_python 2014年

44

投票支持杰森·科恩(Jason Cohen)的论点,因为它的论据很好。让我逐步解散它。;-)

  • NPE的JavaDoc明确地说,“空对象的其他非法使用”。如果仅限于运行时在不应该遇到null的情况下,则可以更简洁地定义所有此类情况。

  • 如果您假设做错了事,那将无济于事,但假设正确应用了封装,您真的不应该在意或注意到是否对空值进行了不适当的引用,而不是方法是否检测到不适当的空值并触发了异常。

  • 由于多种原因,我选择NPE而不是IAE

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

总的来说,我感到NPE的弊端很大,因为传统上将NPE与未能遵循快速失败原则的代码相关联。那,加上JDK无法用消息字符串填充NPE,确实造成了强烈的负面情绪,这是没有根据的。实际上,从运行时角度来看,NPE和IAE之间的区别严格来说就是名称。从这个角度来看,名称越精确,您给呼叫者的清晰度就越高。


大多数未检查的异常之间的区别只是名称。
托尔比约恩Ravn的安徒生

20

这是一个“圣战”风格的问题。换句话说,这两种选择都是好的,但是人们会有自己的偏好,可以捍卫自己的生命。


不,这个问题只有一个正确的答案,那就是在方法的输入不正确时使用throw IllegalArgument异常。同样在开发环境中,您可以使用断言来检查输入的有效性并抛出适当的异常;)
Mr.Q

@ Mr.Q我认为,NullPointerException应该抛出:它是约定的JDK使用,并且需要的接口,它的更具体的(就像IndexOutOfBoundsException等),等等
所罗门会员名:Ucko

kekekekkek ...:D
Yousha Aleayoub,

17

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

所以,如果你使用它和它的nullNullPointer。如果它在传递和它的nullIllegalArgument


9

Apache Commons Lang有一个NullArgumentException,它可以完成此处讨论的许多事情:它扩展了IllegalArgumentException,并且它的唯一构造方法采用了应该为非null的参数名称。

虽然我觉得抛出类似NullArgumentException或IllegalArgumentException之类的东西可以更准确地描述特殊情况,但我和我的同事还是选择遵从Bloch关于该主题的建议。


7
注意他们删除它从公地lang3:apache-commons.680414.n4.nabble.com/...
artbristol

7

我完全同意所说的话。早期失败,快速失败。相当不错的异常口头禅。

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

我的2美分


7

实际上,在我的拙见中,抛出IllegalArgumentException或NullPointerException的问题仅是对Java异常处理了解不足的少数人的“圣战”。通常,规则很简单,如下所示:

  • 必须尽可能快地表明参数约束违规(->快速失败),以避免出现难以调试的非法状态
  • 如果出于任何原因导致无效的空指针,则抛出NullPointerException
  • 如果数组/集合索引非法,则抛出ArrayIndexOutOfBounds
  • 如果数组/集合大小为负数,则抛出NegativeArraySizeException
  • 如果上面没有涉及非法参数,并且您没有其他更特定的异常类型,则将IllegalArgumentException当作废纸bas
  • 另一方面,如果由于某些正当原因而无法通过快速失败来避免在字段内违反约束,则将其作为IllegalStateException或更具体的检查异常进行捕获并重新抛出。在这种情况下,切勿传递原始的NullPointerException,ArrayIndexOutOfBounds等!

至少有三个很好的理由反对将各种参数约束违规映射到IllegalArgumentException的情况,第三个原因可能是如此严重以至于标记了实践不良样式:

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

(2)映射异常实际上导致由单继承引起的另一种异常:所有Java异常都是类,因此仅支持单继承。因此,由于子类只能从一个继承自另一个继承,所以无法创建一个真正表示NullPointerException和IllegalArgumentException的异常。因此,在参数为null的情况下抛出IllegalArgumentException,每当程序尝试以编程方式纠正问题时,例如通过将默认值输入重复调用中,API用户就更难区分问题。

(3)映射实际上会造成错误掩盖的危险:为了将违反参数约束的行为映射到IllegalArgumentException,您将需要在每个具有受限参数的方法中编写外部try-catch。但是,仅在此catch块中捕获RuntimeException是不可能的,因为这可能会将由您内部使用的libery方法抛出的已记录的RuntimeException映射到IllegalArgumentException中,即使它们不是由参数约束冲突引起的。因此,您需要非常具体,但是即使您不小心将另一个API的未记录的运行时异常(即错误)映射到您的API的IllegalArgumentException中,这种保护也无法为您提供保护。

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


6

如果使用IllegalArgumentException(String message)来声明参数无效并提供尽可能多的详细信息,这是公认的做法。也就是说,在异常非null的情况下,发现参数为null,您可以执行一些操作像这样:

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

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


6

引发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,它会错过它。


5

一些集合假设null使用NullPointerException而不是拒绝了该集合IllegalArgumentException。例如,如果您将一个包含的集合null与一个拒绝的集合进行比较null,则第一个集合将调用containsAll另一个并捕获它的NullPointerException-但不是IllegalArgumentException。(我正在查看的实现AbstractSet.equals。)

你可以合理地认为,以这种方式使用unchecked异常是一个反模式,即含有比较集合null到不能包含集合null是一个可能的错误,真的应该产生一个异常,或将null在所有集合中是一个坏主意。但是,除非您愿意说equals在这种情况下应该抛出异常,否则您会牢记NullPointerException在某些情况下需要这样做,而在其他情况下则不需要。(“ IAE在NPE之前,但在'c'之后...”)


我看不到容器如何根据集合中的元素抛出NPE。抛出(自动)NPE的唯一原因是集合本身为null(在这种情况下,抛出NPE是因为它试图访问其迭代器)。但是,这确实提出了一个问题:是否应该检查空输入,或者是否应该传播空输入直到尝试访问空输入。
Alowaniak '16

2
new TreeSet<>().containsAll(Arrays.asList((Object) null));NPE因为List包含而抛出null
克里斯·波维尔克

1
确实,TreeSet#contains引发NPE“如果指定的元素为null,并且此集合使用自然顺序,或者其比较器不允许使用null元素”。只看了允许空值的AbstractSet,我不好。我个人觉得它很奇怪,尽管它不会仅仅返回false,因为在那种情况下,不可能添加null。
Alowaniak '16

5

作为一个主观的问题,应将其关闭,但仍处于打开状态:

这是我以前的工作场所所使用的内部政策的一部分,并且效果很好。这些全都来自记忆,所以我不记得确切的用词了。值得注意的是,他们没有使用检查异常,但这超出了问题的范围。他们确实使用的未经检查的异常分为3个主要类别。

NullPointerException:不要故意抛出。当取消引用空引用时,仅由VM抛出NPE。应尽一切可能确保不会抛出这些错误。@Nullable和@NotNull应该与代码分析工具结合使用以查找这些错误。

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

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

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

就像我说的那样,该系统确实运行良好,需要有人来解释为什么存在这种区别:“根据错误的类型,您很容易确定要做什么。即使您实际上无法弄清楚找出出了什么问题,您可以找出在哪里捕获该错误并创建其他调试信息。”

NullPointerException:处理Null大小写或放入断言中,以便不引发NPE。如果您声明,则只是其他两种类型之一。如果可能,请继续进行调试,就像断言首先存在于此一样。

IllegalArgumentException:您的呼叫站点有问题。如果传入的值来自另一个函数,请找出为什么接收到不正确的值。如果传入参数之一,则错误会检查调用堆栈,直到找到未返回期望值的函数。

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

无论如何,他的观点是您只能将IllegalArgumentAssertions复制到堆栈中。您无法在堆栈上传播IllegalStateExceptions或NullPointerExceptions,因为它们与您的功能有关。


4

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


9
NPE上的JavaDoc有另一种观点:“应用程序应抛出此类的实例以指示对null对象的其他非法使用。” 别那么
专心

4

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


我采用了“抛出新的IllegalArgumentException(“ foo == null”)“方法。你总有需要登录变量名(要确定你正在寻找正确的sttatement等)
托尔比约恩Ravn的安徒生

4

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

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));

1
这将使创建异常的开销增加一倍,并且并没有真正的帮助,因为捕获NullPointerException不会执行任何操作。唯一可以帮助的是IllegalNullPointerArgumentException extends IllegalArgumentException, NullPointerException,但是我们没有多重继承。
maaartinus 2014年

我认为,更具体的异常应该由更一般的异常包装。NPE用于表达,而IAE用于方法。由于方法包含包含表达式的语句,因此IAE更通用。
Sgene9

关于开销,我不知道。但是由于除了在中间更改了异常的名称之外,堆栈跟踪基本上是相同的,所以我认为对于双重异常应该没有太多的开销。如果担心开销,则可以使用“ if”语句返回null或-1而不是引发异常。
Sgene9

4

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

IllegalArgumentException 当方法接收到的参数格式与方法预期的格式不同时抛出。


3

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


0

理想情况下,不应引发运行时异常。应该为您的方案创建一个已检查的异常(业务异常)。因为如果抛出并记录了这些异常中的任何一个,则在浏览日志时会误导开发人员。取而代之的是,业务异常不会造成这种恐慌,通常在对日志进行故障排除时会被忽略。


-1

指向以上两个异常的链接中的定义为IllegalArgumentException:被抛出以指示方法已传递了非法或不适当的参数。NullPointerException:当应用程序在需要对象的情况下尝试使用null时抛出。

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

我希望这有助于将两者放在一起。


1
重要的一点是使用空值的是应用程序,而不是运行时。因此,“当方法被传递了非法或不合适的参数时”与“当应用程序使用null时”之间存在相当大的重叠。从理论上讲,如果应用为要求非空的字段传递了空值,则将同时满足两个条件。
Christopher Smith,2009年

-1

如果它是“设置者”,或者是我以后要让某个成员使用的某个地方,那么我倾向于使用IllegalArgumentException。

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

如果我要覆盖某个方法,则将使用该覆盖方法所使用的任何东西。


-1

您应该抛出一个IllegalArgumentException,因为它将使程序员很明显他做了无效的事情。开发人员习惯于看到VM抛出的NPE,以至于任何程序员都不会立即意识到自己的错误,而会开始四处寻找,甚至更糟糕的是,将代码归咎于“笨拙”。


4
抱歉,如果程序员在遇到任何异常时都“随意地”四处张望……更改异常的名称不会有多大帮助。
Christopher Smith,2009年

-1

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

GaryF和tweakt删除了推荐使用NPE的“有效Java”(我发誓)参考。查看其他优质API的构建方式是了解如何构建API的最佳方法。

另一个很好的例子是查看Spring API。例如,org.springframework.beans.BeanUtils.instantiateClass(构造函数ctor,Object [] args)具有Assert.notNull(ctor,“构造函数不得为null”)行。org.springframework.util.Assert.notNull(Object object,String message)方法检查传入的参数(对象)是否为null,如果存在,则抛出新的IllegalArgumentException(message),然后将该异常捕获到组织中。 springframework.beans.BeanUtils.instantiateClass(...)方法。


-5

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


运行时不会包含有意义的味精。
mP。

实际上,此评论可能会得出其他意见。让虚拟机发言,NPE而程序员IAE则愿意在虚拟机之前发言。
Jin Kwon

1
昂贵?我不认为== null会那么昂贵...此外,null参数只能存储供以后使用,并且在方法调用后很长一段时间会引发异常,从而使错误更难跟踪。或者,您可以在使用null参数之前创建一个昂贵的对象,依此类推。早期发现似乎是一个不错的选择。
PhiLho

对这个答案的否定表决是对背后硬件的误解。当然,硬件检查(CPU执行的检查)比显式检查便宜。取消引用null是SegmentationFault(SegV)特殊情况(访问该进程不拥有的页面),CPU / OS检查并由JRE处理该异常,并抛出NullPointerException作为特殊情况。
digital_infinity
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.