IllegalArgumentException or NullPointerException for a null parameter?我有一个简单的属性setter方法, 您应该使用 首先,npe javadoc明确列出了npe适合的情况。注意,当 第二,当您在堆栈跟踪中看到一个NPE时,您会假设什么?可能是有人取消了对一个 第三,由于IAE是为验证参数而设计的,所以您必须假设它是默认的例外选择,那么为什么您要选择NPE呢?当然不是针对不同的行为——您真的希望调用代码与IAE分开捕获NPE,并因此做一些不同的事情吗?您是否试图传达更具体的错误消息?但无论如何,您可以在异常消息文本中这样做,因为对于所有其他不正确的参数,您应该这样做。 第四,所有其他不正确的参数数据都是依斯克拉汽车电器有限公司的,为什么不一致呢?为什么一个非法的 最后,我接受JAVA API部分使用这种方式使用NPE的其他答案给出的参数。但是,Java API与从异常类型到命名约定的任何东西都不一致,所以我认为只是盲目复制(您最喜欢的部分)Java API并不是一个足够好的论点来胜过其他的考虑因素。 如果不希望 标准是投掷
我一直赞成将EDOCX1 0的参数用于空参数,直到今天,当我注意到Java 7中的EDCOX1 1Ω方法时。用这种方法,而不是:
你可以做到:
如果你传递的参数是 假设该方法是在EDOCX1中的右边Bang.Of 4,我认为它的存在是一个非常有力的指示,即抛出EDCOX1×2是"Java的做事方式"。 我想我已经决定了。 请注意,关于硬调试的论点是假的,因为您当然可以向 我倾向于遵循JDK库的设计,尤其是集合和并发(JoshuaBloch、DougLea,这些人知道如何设计可靠的API)。无论如何,JDK中的许多API都主动抛出 例如,用于
扔自己的NPE是完全正确的。约定是在异常消息中包含空的参数名称。 模式是:
无论您做什么,都不要允许设置一个坏值,并在以后其他代码尝试使用它时抛出异常。这使得调试成为一场噩梦。你应该始终遵循"快速失败"的原则。 投票支持杰森·科恩的论点,因为它得到了很好的呈现。让我一步一步地把它肢解。;-)
总的来说,我觉得NPE受到了很大的指责,因为传统上它与未能遵循快速失败原则的代码相关。再加上JDK未能用消息字符串填充NPE,真的造成了一种强烈的负面情绪,这是没有充分根据的。实际上,从运行时的角度来看,NPE和IAE之间的区别是严格的名称。从这个角度来看,你对名字的理解越精确,你对来电者的理解就越清晰。 这是一个"圣战"式的问题。换句话说,这两种选择都是好的,但人们会有他们的偏好,他们会捍卫到死亡。 如果这是一个 所以,如果你用的是 ApacheCommonsLang有一个NullArgumentException,它执行了这里讨论的许多事情:它扩展了IllegalArgumentException,并且它的唯一构造函数使用了应该为非空的参数的名称。 虽然我觉得抛出NullArgumentException或IllegalArgumentException之类的东西更准确地描述了异常情况,但我和同事们还是选择了遵从布洛赫关于这个问题的建议。 对所说的话再同意不过了。及早失败,快速失败。非常好的例外咒语。 关于抛出哪一个异常的问题主要是个人品味的问题。在我看来,IllegalArgumentException比使用NPE更具体,因为它告诉我问题出在我传递给方法的参数上,而不是在执行方法时生成的值上。 我的2分钱 实际上,抛出非法的AgulMutExtExpReor或Null PoExtExchange的问题在我看来只是少数人的"神圣战争",对Java中的异常处理有着难以理解的理解。一般来说,规则很简单,如下所示:
至少有三个非常好的理由反对将所有类型的参数约束违反映射到IllegalArgumentException,第三个理由可能非常严重,以致于标记实践的不良风格: (1)程序员不能安全地假定所有违反参数约束的情况都会导致IllegalArgumentException,因为如果没有更具体的异常类型,大多数标准类都将此异常用作废纸篓。尝试将所有违反参数约束的情况映射到API中的IllegalArgumentException只会导致程序员对使用类感到沮丧,因为标准库大多遵循违反您的规则的不同规则,而且大多数API用户也会使用它们! (2)映射异常实际上会导致由单一继承引起的异常类型:所有Java异常都是类,因此只支持单继承。因此,无法创建一个异常,也就是说,空指针异常和非法参数异常,因为子类只能从一个或另一个继承。因此,在空参数的情况下引发IllegalArgumentException会使API用户在程序尝试以编程方式更正问题时更难区分问题,例如通过向调用repeat中输入默认值! (3)映射实际上会造成bug屏蔽的危险:为了将参数约束冲突映射到IllegalArgumentException,需要在每个具有任何约束参数的方法中编写一个外部try catch。但是,在这个catch块中简单地捕获runtimeexception是不可能的,因为这样做的风险是将您的自由方法抛出的文档化runtimeexception映射到illegalargumentexception中,即使它们不是由参数约束冲突引起的。因此,您需要非常具体,但即使这样做也不能保护您免受意外将另一个API的未记录运行时异常(即bug)映射到您的API的IllegalArgumentException的情况。因此,即使是最仔细的映射也有可能掩盖其他库制造商的编程错误,因为参数约束违反了方法的用户,这只是一种不体面的行为! 另一方面,在标准实践中,规则保持简单,异常原因保持无遮拦和特定。对于方法调用方,规则也很简单:-如果由于传递了非法值而遇到任何类型的文档化运行时异常,请使用默认值重复调用(对于此特定异常是必需的),或者更正代码。-另一方面,如果您包含了一个运行时异常,而该异常没有为给定的参数集记录下来,那么请将一个错误报告提交给方法的创建者,以确保他们的代码或他们的文档被修复。 如果使用IllegalArgumentException(字符串消息)来声明参数无效并尽可能给出详细信息,则接受的做法是…因此,要说发现一个参数为空,而异常为非空,您可以这样做:
实际上,您没有理由隐式使用"NullPointerException"。NulLoPoExtExchange是Java虚拟机在试图在空引用上执行代码时抛出的一个异常(如ToStTrand())。 抛出一个
…有两个论点清单: 作为一个主观问题,这应该是封闭的,但由于它仍然是开放的: 这是我以前工作的地方采用的内部政策的一部分,而且效果非常好。这都是记忆造成的,所以我记不清确切的措辞。值得注意的是,他们没有使用检查异常,但这超出了问题的范围。他们使用的未经检查的异常分为三大类。 NullPointerException:不要有意抛出。当取消对空引用的引用时,仅由VM引发NPE。应尽一切可能确保不会抛出这些文件。@nullable和@notnull应与代码分析工具一起使用以查找这些错误。 IllegalArgumentException:当函数的参数不符合公共文档时引发,这样就可以根据传入的参数识别和描述错误。手术室的情况属于这一类。 IllegalstateException:调用函数时引发,该函数的参数在传递时是意外的,或者与方法所属对象的状态不兼容。 例如,有两个内部版本的indexoutofboundsException用于具有长度的对象。一个是IllegalstateException的子类,在索引大于长度时使用。IllegalArgumentException的另一个子类,在索引为负时使用。这是因为您可以向对象添加更多的项,并且参数将有效,而负数则永远无效。 正如我所说,这个系统工作得非常好,需要有人来解释为什么会有这样的区别:"根据错误的类型,您可以很容易地找到要做的事情。即使您实际上无法找出出错的地方,也可以找出在哪里捕获错误并创建其他调试信息。" NullPointerException:处理空的大小写或放入断言,这样就不会引发NPE。如果您输入的断言只是其他两种类型中的一种。如果可能的话,继续调试,就好像断言是在那里一样。 IllegalArgumentException:您的呼叫站点出错。如果要传递的值来自另一个函数,请找出收到错误值的原因。如果传递的是某个参数,则会传播错误,检查调用堆栈,直到找到不返回预期值的函数为止。 IllegalstateException:您没有按正确的顺序调用函数。如果您正在使用某个参数,请检查它们并抛出描述该问题的IllegalArgumentException。然后,你可以将脸颊向上延伸,直到你找到问题所在。 不管怎样,他的观点是你只能把非法的断言复制到堆栈上。无法将IllegalstateExceptions或NullPointerExceptions向上传播,因为它们与您的函数有关。 一般来说,开发人员不应该抛出NullPointerException。当代码试图取消引用值为空的变量时,运行时会引发此异常。因此,如果您的方法想要显式地不允许空值,而不是刚好让空值引发NullPointerException,则应该抛出IllegalArgumentException。 二分法…它们不重叠吗?只有不重叠的部分才能形成二分法。正如我看到的:
一些托收假设使用 您可以合理地认为,以这种方式使用未经检查的异常是一种反模式,将包含 尝试访问当前值为空的引用变量的对象时引发NullPointerException 当方法接收的参数格式与方法预期的不同时引发IllegalArgumentException 我想从其他非法参数中找出空参数,所以我从IAE派生了一个名为nullArgumentException的异常。甚至不需要读取异常消息,我知道一个空参数被传递到了一个方法中,通过读取消息,我发现了哪个参数是空的。我仍然使用IAE处理程序捕获nullArgumentException,但是在我的日志中,我可以很快看到不同之处。 根据您的场景, 理想情况下,不应引发运行时异常。应为您的方案创建选中的异常(业务异常)。因为如果这些异常中的任何一个被抛出并被记录,它会在浏览日志时误导开发人员。相反,业务异常不会造成这种恐慌,并且通常在对日志进行故障排除时被忽略。 从链接到上述两个例外的定义是IllegalArgumentException:引发以指示方法已传递非法或不适当的参数。NullPointerException:在需要对象的情况下,当应用程序尝试使用空值时引发。 这里最大的区别是,在检查方法的参数是否有效时,应该使用IllegalArgumentException。NullPointerException应该在对象为空时"使用"时使用。 我希望这有助于把两者放在一个角度上。 如果它是一个"setter",或者在我要让一个成员稍后使用的地方,我倾向于使用IllegalArgumentException。 如果这是我现在要在方法中使用的(取消引用),我会主动抛出一个nullpointerException。我更喜欢这个,而不是让运行时做它,因为我可以提供一个有用的消息(看起来运行时也可以这样做,但这是对另一天的咆哮)。 如果我要重写一个方法,我将使用被重写的方法使用的任何内容。 在这种情况下,IllegalArgumentException使用您的API向用户传递"不应为空"的明确信息。正如其他论坛用户指出的那样,只要你想用你的API把正确的信息传达给用户,你就可以使用NPE。 GaryF和TWIDT删除了推荐使用NPE的"有效Java"(我发誓)。查看如何构建其他好的API是了解如何构建API的最佳方法。 另一个很好的例子是查看SpringAPI。例如,org.springframework.beans.beanutils.instantiaclass(constructor ctor,object[]args)有一个assert.not null(ctor,"constructor must not be null")行。org.springframework.util.assert.notnull(object object,string message)方法检查传入的参数(object)是否为空,如果为空,则抛出一个新的IllegalArgumentException(message),然后在org.springframework.beans.beanutils.instantialClass(…)方法中捕获。 您应该抛出一个IllegalArgumentException,因为它将使程序员明显地看到他做了一些无效的事情。开发人员已经习惯于看到虚拟机抛出的NPE,以至于任何程序员都不会立即意识到自己的错误,并且会开始随机地四处查看,或者更糟的是,将代码归咎于"错误"。 如果您选择抛出一个NPE,并且在方法中使用了参数,那么显式检查空值可能是多余的,而且代价高昂。我想虚拟机已经为你做到了。 |