Java构造函数风格:检查参数不为空。
Java构造函数风格:检查参数不为空。
如果一个类接受一些参数,但这些参数都不能为null
,那么有哪些最佳实践呢?\n以下是显而易见的,但异常有点不明确:\n
public class SomeClass { public SomeClass(Object one, Object two) { if (one == null || two == null) { throw new IllegalArgumentException("参数不能为空"); } //... } }
\n在这里,异常会告诉你哪个参数为空,但构造函数现在变得有点丑陋:\n
public class SomeClass { public SomeClass(Object one, Object two) { if (one == null) { throw new IllegalArgumentException("one不能为空"); } if (two == null) { throw new IllegalArgumentException("two不能为空"); } //... }
\n在这里,构造函数更整洁,但构造函数中的代码实际上并不是真正的构造函数:\n
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不能为空"); } //... } public void setTwo(Object two) { if (two == null) { throw new IllegalArgumentException("two不能为空"); } //... } }
\n这些风格中哪种是最好的?\n或者是否有更广泛接受的另一种替代方案?
Java构造函数风格:检查参数是否为空
在Java中,构造函数是用来创建对象并初始化其状态的特殊方法。在编写构造函数时,我们通常需要检查参数是否为空,以确保传入的参数是有效的。如果参数为空,我们可以选择抛出IllegalArgumentException或NullPointerException异常。
然而,为了简化参数的检查过程,我们可以使用一些库来帮助我们进行前置条件检查。Google Guava是一个流行的Java库,其中的许多代码都使用了com.google.common.base.Preconditions类来进行参数检查。
使用Google Guava的Preconditions类,我们可以将以下代码:
if (count <= 0) { throw new IllegalArgumentException("must be positive: " + count); }
简化为:
checkArgument(count > 0, "must be positive: %s", count);
其中checkArgument方法是Preconditions类提供的静态方法之一,用于检查给定的条件是否为真,如果条件为假,则抛出IllegalArgumentException异常。
另外,Preconditions类还提供了checkNotNull方法,该方法用于检查参数是否为空,并在参数为空时抛出NullPointerException异常。这个方法在Guava库中被广泛使用。
下面是一个示例构造函数,使用了checkNotNull来检查参数是否为空:
import static com.google.common.base.Preconditions.checkNotNull; public class SomeClass { private Object one; private Object two; public SomeClass(Object one, Object two) { this.one = checkNotNull(one); this.two = checkNotNull(two, "two can't be null!"); //... } }
在这个示例中,如果传入的参数one为空,checkNotNull会抛出NullPointerException异常;如果传入的参数two为空,checkNotNull会抛出带有自定义错误消息的NullPointerException异常。
另外,关于IllegalArgumentException和NullPointerException的选择,有一些争议。根据《Effective Java》一书的建议,如果调用者传递了一个不允许为空的参数为null,应该抛出NullPointerException异常而不是IllegalArgumentException异常。
然而,Java文档中对于这两个异常的描述并没有明确规定。NullPointerException通常用于表示访问null引用的成员变量时抛出异常,但在某些情况下也可以用于表示参数为null的非法值。
总之,使用参数检查库,如Google Guava的Preconditions类,可以简化构造函数中对参数的非空检查。这样可以使代码更加简洁和可读,并且提供了一种统一的方式来处理参数为空的情况。
Java 7在API中添加了java.util.Objects.requireNonNull()
。因此,检查所有参数是否为null可以简化为以下短列表:
this.arg1 = Objects.requireNonNull(arg1, "arg1 must not be null"); this.arg2 = Objects.requireNonNull(arg2, "arg2 must not be null");
需要注意的是:
- 确保不要颠倒两个参数的顺序 - 第二个参数是在第一个参数为null时抛出的NPE的消息(如果颠倒了它们,那么检查永远不会失败)
- 另一个最佳实践:如果可能的话,将所有类成员设置为final(这样您就可以确保:当某个对象成功创建时,所有成员都不为null,并且它们不会随时间而变化)
这应该是现在应该接受的答案。不需要第三方库+较新的JDK...
Java构造函数风格:检查参数不为空
在Java编程中,我们经常需要在构造函数中检查参数是否为空。这是为了确保我们的代码在运行时不会出现空指针异常。但是,如何正确地检查参数并处理可能的空值是一个有争议的问题。
首先,我们需要讨论为什么在构造函数中检查参数是否为空很重要。这是因为构造函数是在创建对象时调用的,它们负责初始化对象的各个属性。如果我们允许构造函数接受空值参数,那么在对象创建后,我们将无法确定某些属性的值是否为空。这可能导致对象在使用过程中出现问题,甚至导致程序崩溃。因此,通过在构造函数中检查参数是否为空,我们可以确保对象被正确地初始化,并且可以避免后续的错误和异常。
解决这个问题的一种方法是使用Apache Commons库中的Validate.notNull(obj, message)
方法。通过使用这个方法,我们可以在构造函数中检查参数是否为空,并在参数为空时抛出异常。这样,我们就可以在构造函数中明确地告诉用户哪个参数为空了。下面是一个使用该方法的示例:
public SomeClass(Object one, Object two) { Validate.notNull(one, "one can't be null"); Validate.notNull(two, "two can't be null"); ... }
除了在构造函数中检查参数是否为空之外,还可以选择将检查放在setter方法中。这样做的好处是可以在每次设置属性时都进行参数检查,从而保证对象的一致性。然而,这种方法也有一些争议,一些人认为如果构造函数已经检查了参数并防止了空值,那么如果setter方法接受空值将会是一个bug。
在上述讨论中,某些情况下了使用Guava库中的checkArgument()
方法来实现参数检查。这个方法可以在构造函数中使用,类似于Validate.notNull()方法。使用Guava库可以提供更多的参数检查功能,以及与Apache Commons库的比较。
我们可以通过在构造函数中检查参数是否为空来确保对象的正确初始化,并避免后续的错误和异常。在选择检查的位置时,可以考虑使用Apache Commons库或Guava库提供的方法来简化代码。无论选择哪种方法,都应该注意保证对象的一致性,并避免可能的bug。