Java构造函数样式:检查参数不为null

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (269)

如果你有一个接受一些参数但不允许它们被允许的类的最佳实践是null什么?

以下是显而易见的,但有一点不明确:

public class SomeClass
{
     public SomeClass(Object one, Object two)
     {
        if (one == null || two == null)
        {
            throw new IllegalArgumentException("Parameters can't be null");
        }
        //...
     }
}

这里的异常让你知道哪个参数是null,但是构造函数现在很丑陋:

public class SomeClass
{
     public SomeClass(Object one, Object two)
     {
        if (one == null)
        {
            throw new IllegalArgumentException("one can't be null");
        }           
        if (two == null)
        {
            throw new IllegalArgumentException("two can't be null");
        }
        //...
  }

这里的构造函数是整洁的,但现在构造函数代码并不在构造函数中:

public class SomeClass
{
     public SomeClass(Object one, Object two)
     {
        setOne(one);
        setTwo(two);
     }


     public void setOne(Object one)
     {
        if (one == null)
        {
            throw new IllegalArgumentException("one can't be null");
        }           
        //...
     }

     public void setTwo(Object two)
     {
        if (two == null)
        {
            throw new IllegalArgumentException("two can't be null");
        }
        //...
     }
  }

哪种风格最好?

或者有更广泛接受的替代方案吗?

提问于
用户回答回答于

第二或第三。

因为它告诉用户你的API究竟出了什么问题。

用于Validate.notNull(obj, message)commons-lang的较不详细的使用。因此你的构造函数看起来像这样:

public SomeClass(Object one, Object two) {
    Validate.notNull(one, "one can't be null");
    Validate.notNull(two, "two can't be null");
    ...
}

将支票放入二传手也是可以接受的,具有相同的详细评论。如果你的二传手也有保持对象一致性的角色,你也可以选择第三个。

用户回答回答于

您可以使用旨在促进先决条件检查的许多库中的一个。谷歌Guava中的许多代码使用com.google.common.base.Preconditions

在自己的方法开始时调用简单的静态方法来验证正确的参数和状态。这允许构造如 if (count <= 0) { throw new IllegalArgumentException("must be positive: " + count); } 以更紧凑的方式取代 checkArgument(count > 0, "must be positive: %s", count);

checkNotNull广泛使用。然后你可以写:

 import static com.google.common.base.Preconditions.checkNotNull;
 //...

 public SomeClass(Object one, Object two) {
     this.one = checkNotNull(one);
     this.two = checkNotNull(two, "two can't be null!");
     //...
 }

大多数方法都会重载,以便不会收到错误消息,固定的错误消息或带有可变参数的模板化错误消息。

关于IllegalArgumentExceptionvsNullPointerException

当你的原始代码抛出IllegalArgumentExceptionnull论点,番石榴的Preconditions.checkNotNull抛出NullPointerException来代替。

以下是Effective Java 2nd Edition的一句话:第60项:赞成使用标准例外

有争议的是,所有错误的方法调用归结为非法论证或非法论述,但其他例外标准用于某些非法论证和状态。如果一个调用者传递null了一些禁止使用空值的参数,那么惯例NullPointerException将被抛出,而不是IllegalArgumentException

A NullPointerException不保留用于访问null参考成员的权限; 当参数是null非法值时抛出它们是非常标准的。

System.out.println("some string".split(null));
// throws NullPointerException

扫码关注云+社区