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

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

当前回答

可以在方法调用之前使用拦截器。这就是面向方面编程所关注的。

假设M1(对象测试)是一个方法,M2是一个在方法调用之前应用方面的方法,M2(对象测试2)。如果test2!=null则调用M1,否则执行另一件事。它适用于所有要应用方面的方法。如果要为实例字段和构造函数应用方面,可以使用AspectJ。对于方法方面,Spring也是最佳选择。

其他回答

总而言之,避免声明

if (object != null) {
    ....
}

由于java7,您可以使用Objects方法:Objects.isNull(对象)Objects.nonNull(对象)Objects.requireOnNull(对象)Objects.equals(object1,object2)从java8开始,您可以使用Optional类(何时使用)

object.ifPresent(obj->…);java 8

object.ifPresentOrElse(对象->…,()->…);java 9

依靠方法契约(JSR305)并使用FindBugs。用annotations@javax.annotation.Nullable和@javax.annotation.Nonnnual标记代码。还提供了前提条件。前提条件.checkNotNull(对象);在特殊情况下(例如字符串和集合),可以使用apachecommons(或Google guava)实用程序方法:

公共静态布尔isEmpty(CharSequence cs)//apache CollectionUtils公共静态布尔isEmpty(集合coll)//apacheStringUtils公共静态布尔isEmpty(Map Map)//apache MapUtils公共静态布尔isNullOrEmpty(@Nullable String字符串)//Guava字符串

当您需要在null时分配默认值时,请使用apachecommons-lang

公共静态对象defaultIfNull(对象对象,对象defaultValue)

我尝试过NullObjectPattern,但对我来说并不总是最好的方法。有时,“不采取行动”并不合适。

NullPointerException是一个运行时异常,这意味着它是开发人员的错,并且凭借足够的经验,它会准确地告诉您错误在哪里。

现在来回答:

尽量将所有属性及其访问器设为私有,或者避免将它们暴露给客户端。当然,您可以在构造函数中设置参数值,但通过缩小范围,您不会让客户端类传递无效值。如果需要修改值,可以始终创建新对象。您只检查构造函数中的值一次,在其他方法中,您几乎可以确定这些值不为空。

当然,经验是理解和应用这一建议的更好方式。

字节

还有一种选择:

下面的简单函数有助于隐藏空检查(我不知道为什么,但我没有发现它是同一个公共库的一部分):

public static <T> boolean isNull(T argument) {
    return (argument == null);
}

你现在可以写了

if (!isNull(someobject)) {
    someobject.doCalc();
}

这是IMO更好的表达方式!=无效的

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()方法中的第二个值(字符串),因为即使有反射(无论如何都不是本文的主题…),也无法轻松检测传入的变量名。

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

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

只是永远不要使用null。不要允许。

在我的类中,大多数字段和局部变量都有非空的默认值,我在代码中的任何地方都添加了契约语句(总是在断言上),以确保这是强制执行的(因为它比让它作为NPE出现然后必须解析行号等更简洁、更具表达力)。

一旦我采用了这种做法,我注意到问题似乎会自行解决。你会在开发过程中很早就发现事情,只是偶然发现自己有一个弱点。。更重要的是。。它有助于封装不同模块的关注点,不同模块可以相互“信任”,不再在代码中添加if=nullelse结构!

这是一种防御性编程,从长远来看,代码会更加干净。始终对数据进行净化,例如在这里通过强制执行严格的标准,问题就会消失。

class C {
    private final MyType mustBeSet;
    public C(MyType mything) {
       mustBeSet=Contract.notNull(mything);
    }
   private String name = "<unknown>";
   public void setName(String s) {
      name = Contract.notNull(s);
   }
}


class Contract {
    public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}

合同就像是小型单元测试,即使在生产中也始终在运行,当事情失败时,你知道原因,而不是随机的NPE,你必须设法弄清楚。