是否可以通过编程方式抛出NullPointerException?

str*_*ine 44 java exception-handling nullpointerexception throw

当有后置条件时,方法的返回值不能为空,可以做什么?

我可以

assert returnValue != null : "Not acceptable null value";
Run Code Online (Sandbox Code Playgroud)

断言可以关闭!

所以可以这样做

if(returnValue==null)
      {
           throw new NullPointerException("return value is null at method AAA");
      }
Run Code Online (Sandbox Code Playgroud)

或者,对于这样的条件,使用用户定义的异常(如NullReturnValueException)会更好吗?

Rom*_*man 61

我建议你永远不要NullPointerException自己扔.

正如ThorbjørnRavnAndersen在下面的评论中所说,不这样做的主要原因是你不要把"真实的,坏的NPE"与故意抛出的NPE混在一起.

因此,在您确信自己能够识别"有效"NPE之前,我建议IllegalArgumentException您在想要告诉API用户null不是有效参数值时使用.传递非法null参数时,应记录方法的行为.

另一个(更现代的imho)选项是@NotNull在参数附近使用注释.这是一篇关于使用@NotNull注释的文章.

正如我之前提到的,也可能存在这样的情况:投掷NPE不会让您或您的队友感到困惑:NPE原因应该清晰可辨.

例如,如果你使用一些带有前置条件模块的库Guava,那么我发现使用类似checkNotNull()方法是处理非法传递的空值的一种更好的方法.

checkNotNull(arg, msg)抛出NPE,但是从堆栈跟踪它很清楚,它是由它产生的Preconditions.checkNotNull(),因此它不是一个未知的bug而是预期的行为.

  • 实际上NullPointerException是一个非常好的**方式来告诉,一个参数不应该为null.请参阅Effective Java:*可以说,所有错误的方法调用都归结为非法参数或非法状态,但其他异常标准地用于某些类型的非法参数和状态.如果调用者在某些禁止空值的参数中传递null,则约定表示抛出NullPointerException而不是IllegalArgumentException.* (30认同)
  • 看看javadoc:*应用程序应该抛出此类的实例来指示null对象的其他非法用法.*这对我来说非常清楚.抛出NPE是合法且有效的,并且应该在传入null时对每个非null参数执行.期间. (13认同)
  • @ willi,保持npe仅由运行时抛出而不是你自己的代码,可以很容易地确定npe的严重程度. (5认同)
  • 我同意whiskeysierra.NPE是告诉某些方法参数为null的方法,并且是它的完美例外.不是IllegalArgumentException.将它放在自己的代码中也与Java库代码中抛出的NPE没有什么不同.我按合同编码,因此我的方法的用户得到他应该期望的,如果他读取我的方法的Javadoc.抛出它会阻止代码进一步执行(早期失败); 否则它会在与实际错误位置完全无关的地方失败.NPE应始终认真对待,因为它表示编程错误. (3认同)
  • 最终,这是对 softwareengineering.SE 的讨论,但关于使用代码作为 _model_ 行为的一种方式,尽管有文档,抛出 NPE 没有帮助。从经验丰富的计算机科学家 [CAR Hoare](https://en.wikipedia.org/wiki/Tony_Hoare) 那里得到它,他称空引用的纯粹发明是他的“十亿美元的错误”。比抛出 NPE 更好的是通知调用者输入无效的原因。_好_说输入为空,但_更好_说参数无效,因为空不是有效选项。 (2认同)

wax*_*ing 41

我认为在JVM为您做出之前尽早抛出NPE没有问题 - 特别是对于null参数.关于这一点似乎存在争议,但Java SE库中有很多例子可以做到这一点.我不明白为什么NPE在你无法自己抛出的方面应该是神圣的.

但是,我离题了.这个问题是关于不同的东西.您正在谈论一个后置条件,声明返回值不能为空.在这种情况下肯定是null意味着你在方法中有一个错误?

你怎么会记录这个?"如果返回值意外为空,则此方法抛出NullPointerException"?没有解释这怎么可能发生?不,我会在这里使用断言.异常应该用于可能发生的错误 - 不包括在方法中出现问题时可能发生的事情,因为这对任何人都没有帮助.

  • 在null参数的情况下,`IllegalArgumentException`可能是更合适的抛出异常.`NullPointerException`用于表示尝试对空值执行某些操作.如果NPE是你的目标,那么只需在你的方法中放弃null检查,并且JVM会自然地抛出NPE. (3认同)

Tim*_*sch 28

鉴于这NullPointerException是在Java中传达意外的空值的惯用方法,我建议你抛出标准NullPointerException而不是本土的.还要记住,最小惊喜的原则是建议您不要为存在系统异常类型的情况创建自己的异常类型.

断言很适合调试,但如果你必须处理某些条件就不好,这样就不是处理错误条件的好方法.


Dan*_*lor 11

问题NullPointerException是,当你忘记检查某些东西是否为null或者给出错误的参数为null时它会发生,而不应该.

根据我的经验,Java程序员非常快速地了解到这个异常是由代码中的错误引起的,因此手动抛出它会对大多数人造成极大的混乱.IllegalArgumentException当你传递不可接受的参数时(例如null,其中某些东西不能为null)是更好的主意.

它还触发了另一种启发式方法.NPE =此处有人在代码中出错,IllegalArgumentException=给予该方法的对象无效.

另一方面,javadoc告诉:

应用程序应抛出此类的实例以指示
null对象的其他非法使用.

因此投掷NPE是合法的,但这不是常见做法,所以我建议IllegalArgumentException.

  • 我认为这是不正确的。``NullPointerException`` 确实意味着我忘记检查某些东西。但是当它被方法直接抛出时,如果禁止传入“null”,则实际上存在错误。所以唯一的好办法就是扔NPE。 (2认同)

Aff*_*ffe 7

肯定没有一个反对抛出NullPointerException的普遍规律,但如果你真的应该在这样一个抽象的例子中,很难回答.你不想做的是把人放在试图抓住NullPointerException的位置.像这样的代码(真实的例子,我发誓):

catch (NullPointerException npe) {
  if (npe.getMessage().equals("Null return value from getProdByCode") {
    drawToUser("Unable to find a product for the product type code you entered");
  } 
}
Run Code Online (Sandbox Code Playgroud)

是一个万无一失的指标,你做错了什么.因此,如果null返回值是您实际能够进行通信的某个系统状态的指示符,请使用传递该状态的异常.我可以想到很多情况下,只需查看空指针就可以检查引用是否合理.通常,下一行代码无论如何都会删除nullpointer(或更具信息性的东西)!


Gab*_*ica 6

http://pmd.sourceforge.net/pmd-5.0.1/rules/java/strictexception.html
“避免抛出 NullPointerExceptions。这些令人困惑,因为大多数人会认为虚拟机抛出了它。考虑使用 IllegalArgumentException 代替;这个将被清楚地视为程序员发起的异常。”


Tho*_*sen 5

如果你还记得描述,我会考虑使用NullPointerException .这就是调查人员所使用的(行号可能会改变).还记得记录您的方法在特殊情况下抛出空指针异常.

如果你在开始时检查你的方法参数,throw new IllegalArgumentException("foo==null")我也可以接受.