我使用x!=null以避免NullPointerException。还有其他选择吗?

if (x != null) {
    // ...
}

当前回答

Java中常见的“问题”确实存在。

首先,我的想法是:

我认为,当传递NULL时,如果NULL不是有效值,“吃掉”某些东西是不好的。如果您退出方法时没有出现某种错误,那么这意味着您的方法中没有任何错误,这是不正确的。在这种情况下,您可能会返回null,在接收方法中,您再次检查null,并且它永远不会结束,结果是“if!=null”等。。

因此,IMHO,null必须是阻止进一步执行的关键错误(即,null不是有效值)。

我解决这个问题的方法是:

首先,我遵循以下惯例:

所有公共方法/API始终检查其参数是否为空所有私有方法都不检查null,因为它们是受控制的方法(如果上面没有处理null指针异常,就让它终止)唯一不检查null的其他方法是实用程序方法。他们是公开的,但如果你出于某种原因打电话给他们,你知道你通过了哪些参数。这就像试图在水壶里烧水而不提供水。。。

最后,在代码中,public方法的第一行如下所示:

ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();

注意,addParam()返回self,这样您就可以添加更多的参数来检查。

如果任何参数为空,方法validate()将抛出checked ValidationException(checked或unchecked更多是设计/品味问题,但我的ValidationException已选中)。

void validate() throws ValidationException;

例如,如果“计划”为空,则消息将包含以下文本:

“参数[plans]遇到非法参数值null”

正如您所看到的,用户消息需要addParam()方法中的第二个值(字符串),因为即使有反射(无论如何都不是本文的主题…),也无法轻松检测传入的变量名。

是的,我们知道,在这一行之外,我们将不再遇到空值,因此我们只需安全地调用这些对象上的方法。

这样,代码就干净、易于维护和可读。

其他回答

Java中常见的“问题”确实存在。

首先,我的想法是:

我认为,当传递NULL时,如果NULL不是有效值,“吃掉”某些东西是不好的。如果您退出方法时没有出现某种错误,那么这意味着您的方法中没有任何错误,这是不正确的。在这种情况下,您可能会返回null,在接收方法中,您再次检查null,并且它永远不会结束,结果是“if!=null”等。。

因此,IMHO,null必须是阻止进一步执行的关键错误(即,null不是有效值)。

我解决这个问题的方法是:

首先,我遵循以下惯例:

所有公共方法/API始终检查其参数是否为空所有私有方法都不检查null,因为它们是受控制的方法(如果上面没有处理null指针异常,就让它终止)唯一不检查null的其他方法是实用程序方法。他们是公开的,但如果你出于某种原因打电话给他们,你知道你通过了哪些参数。这就像试图在水壶里烧水而不提供水。。。

最后,在代码中,public方法的第一行如下所示:

ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();

注意,addParam()返回self,这样您就可以添加更多的参数来检查。

如果任何参数为空,方法validate()将抛出checked ValidationException(checked或unchecked更多是设计/品味问题,但我的ValidationException已选中)。

void validate() throws ValidationException;

例如,如果“计划”为空,则消息将包含以下文本:

“参数[plans]遇到非法参数值null”

正如您所看到的,用户消息需要addParam()方法中的第二个值(字符串),因为即使有反射(无论如何都不是本文的主题…),也无法轻松检测传入的变量名。

是的,我们知道,在这一行之外,我们将不再遇到空值,因此我们只需安全地调用这些对象上的方法。

这样,代码就干净、易于维护和可读。

您可以为对象和字符串创建一个通用方法,以便在应用程序中完全使用它-这可以帮助您和您的同事:创建一个类,例如StringUtilities,并添加方法,例如getNullString

public static String getNullString(Object someobject)
{
   if(null==someobject )
        return null;

   else if(someobject.getClass().isInstance("") && 
          (((String)someobject).trim().equalsIgnoreCase("null")|| 
          ((String)someobject).trim().equalsIgnoreCase("")))
        return null;

   else if(someobject.getClass().isInstance(""))
        return (String)someobject;

   else
        return someobject.toString().trim();
}

简单地将此方法称为,

if (StringUtilities.getNullString(someobject) != null)
{ 
  //Do something
}

您可以使用FindBugs。他们还有一个Eclipse插件),可以帮助您查找重复的空检查(除其他外),但请记住,有时您应该选择防御性编程。还有Java合同可能会有所帮助。

我更喜欢这个

public void simpleFunc(SomeObject someObject){
    someObject = someObject != null ? someObject : new SomeObject(null);
    someObject.doSomething();
}

当然,在我的示例中,SomeObject优雅地处理空参数。例如,记录这样的事件,不做任何其他操作。

Java8带来了新的Java.util.Optional类,它可以解决一些问题。至少可以说,它提高了代码的可读性,并且在公共API的情况下,使API的契约对客户端开发人员更加清晰。

它们是这样工作的:

给定类型(Fruit)的可选对象被创建为方法的返回类型。它可以是空的或包含Fruit对象:

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

现在看看这段代码,我们在其中搜索给定Fruit实例的Fruit(水果)列表:

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

您可以使用map()运算符对可选对象执行计算,或从中提取值。orElse()允许您为缺少的值提供回退。

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

当然,检查空/空值仍然是必要的,但至少开发人员意识到该值可能是空的,忘记检查的风险是有限的。

在从头开始使用Optional构建的API中,只要返回值可能为空,并且仅在不能为空时返回纯对象(惯例),客户端代码可能会放弃对简单对象返回值的空检查。。。

当然,Optional也可以用作方法参数,在某些情况下,可能比5或10个重载方法更好地指示可选参数。

可选提供了其他方便的方法,例如允许使用默认值的orElse,以及与lambda表达式一起使用的ifPresent。

我邀请您阅读这篇文章(我撰写这个答案的主要来源),其中很好地解释了NullPointerException(以及一般的空指针)问题以及Optional带来的(部分)解决方案:Java Optional Objects。