Java 捕捉和抛出空点异常的最佳实践?

Java 捕捉和抛出空点异常的最佳实践?,java,nullpointerexception,Java,Nullpointerexception,捕获nullpointerexception似乎不是一个好主意。如果是这样的话,为什么由方法抛出呢?它是否应该被异常捕获 另外,如果我遇到一个空参数(可以是字符串之类的基本类型,也可以是带有字段的类),我应该如何处理它?(假设没有投掷npe) 谢谢这是一个运行时异常,因此不希望深入到程序代码中,只希望JVM在顶层(或接近顶层)或[/update]。由于运行时异常表示严重的问题(通常是严重的编程错误、配置/集成问题等),因此最好让它们传播到顶层,这通常会导致整个线程异常失败。这发出了一个强烈的信号

捕获nullpointerexception似乎不是一个好主意。如果是这样的话,为什么由方法抛出呢?它是否应该被异常捕获

另外,如果我遇到一个空参数(可以是字符串之类的基本类型,也可以是带有字段的类),我应该如何处理它?(假设没有投掷npe)

谢谢

这是一个运行时异常,因此不希望深入到程序代码中,只希望JVM在顶层(或接近顶层)或[/update]。由于运行时异常表示严重的问题(通常是严重的编程错误、配置/集成问题等),因此最好让它们传播到顶层,这通常会导致整个线程异常失败。这发出了一个强烈的信号,表明有问题,需要尽快解决

另见

另外,如果我遇到一个null[…]的参数,我应该如何处理它

一般来说,投掷NPE是可以的。但是,根据情况,你也可以考虑,或者。另见


NPE
RuntimeException
通常在出现编码错误时抛出,这就是为什么捕获它们不是一个好主意。应该做的是修复无法处理空输入的代码

这是问题的第二部分,如何处理空输入。这完全取决于您在代码中合理期望的内容

假设您从数据库表中读取数据,并从可为空的列中读取空值,这绝对不是例外情况,因此您的代码应从业务角度(例如,忽略整行、提示用户输入值或仅使用伪值)将其视为适当的处理方法

但是,如果您正在从不可为null的列(例如主键)读取null值,则应该抛出特定于应用程序的异常,该异常(希望)由应用程序的UI处理


所以答案其实很简单:如果null是正常操作期间可能发生的值,那么相应地处理它,如果不是,则抛出一个已检查的业务异常,而不是一个
NPE

您可能希望捕获NPE的最有可能的情况是在您实现一种框架时,即,您不想终止应用程序,但要报告错误,您可以(明智地)继续应用程序。

如果有人非法向您的方法传递Null,则抛出IllegalArgumentException而不是NP。这更好地描述了错误。

nullpointerexception通常表示错误。如果您不希望出现这样的程序员错误,就不会捕获空指针异常。例如,假设您使用一个类型为P的参数实现了一个方法myMethod

void myMethod(P x)
假设您不希望参数x为null。在这种情况下,您可能不会检查null。为什么?因为您假设使用您的方法的程序员将正确地使用它,并且不会传递null。我不是说在这种情况下是否应该检查null。我只是想回答为什么有时候空指针异常是由一个方法抛出的,并且不应该被捕获。原因如下:您的方法可能会抛出null指针异常,因为有人没有正确使用它(传递null)。使用您的方法的程序员可能知道,如果该方法使用错误,它可能会抛出NullPointerException。但是,即使他错误地使用了您的方法,也不会捕获异常,因为每个人都认为该方法没有被误用

第二个问题:首先,字符串是一个对象,而不是一个基本类型。第二,原语不能为null(原语是int、double、float、chars、boolean等)。现在,如果您遇到一个null参数,并且它不应该为null(换句话说,您收到了一个非法参数),那么您有一些选择:

  • 抛出一个指示参数为null且您的方法希望它不为null的
  • 什么都不要做。假设您的方法使用正确(换句话说,假设没有程序员错误)
  • 用法:
    assert(x!=null)

我个人不喜欢第二种选择,通常更喜欢第二种选择。但是,如果我想确保变量上有一些不变量,我还是使用断言。但是这些只是我的习惯,其他人可能不同意。

为了避免代码中的空检查,在大多数情况下,返回空对象或空列表/映射/集而不是空值是合适的。

这个答案可能很长,但我认为值得

捕获nullpointerexception似乎不是一个好主意

没错,您不应该捕获NullPointerException,也不应该捕获任何运行时异常

如果是这样的话,为什么由方法抛出呢?它是否应该被异常捕获

它用于指示发现编程错误。这些编程错误可以而且应该用代码修复(也就是说,它们是可以预防的)

另外,如果我遇到一个空参数,我应该如何处理它?[…](假设不抛出npe)

这取决于你想用它做什么。对于某些逻辑,可能允许使用
null
值。如果是这种情况,则验证null的存在并对其进行处理,要么提供默认值,要么避免向null发送消息

比如说。假设您有一个账单信息系统,您有一个保存客户信息的代码,您可以选择保存客户额外信息

在这种情况下,可选消息可能为null,您的代码应该验证它的存在

例如:

/**
* ...
* @param - OptionalMessage may be null, include anything else you wan to save.
*/
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   SomeMessage message = SomeMessage.createMessage();
   message.setHeader( c.name() );
   message.setCustomerInformation( c );
   if( optionalMessage != null ) { // is optional? handle it
      message.add( optionalMessage.status() );
      message.add( optionalMessage.summary() );
      message.add( optionalMessage.message() );
    }
 }
}

您可以验证null的存在并记录它

但在本例中,同样的代码也有一个customer作为参数
/**
 * ...
 * @param  c - The customer whose information is to be sent. NotNull 
 * ...
 * @throws NullPointerException if the customer is null
 */
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   SomeMessage message = SomeMessage.createMessage();
   ...
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  return; // I'm done! } 
   // else 
   SomeMessage message = ... 
   ..
}
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  c = new EmptyCustomer() ;} 
   // else 
   SomeMessage message = ... 
   ..
}
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  
     // oh oh  something went wrong. 
     log.fatal("Invalid argument on \"sendCustomerInformation\" );
     throw new MyApplicationException("Dear customer, the information yada yaa"); 
   } 
   ...
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  
     // wait a minute, how could... why did.. what?
     throw new IllegalStateException("Hey, I got null on sendCustomerInformation and this shouldn't happen");
   }
   ...