69 java null constructor coding-style
如果你有一个类接受一些参数但是不允许这些参数,那么最佳实践是null什么?
以下是显而易见的,但例外有点不明确:
public class SomeClass
{
public SomeClass(Object one, Object two)
{
if (one == null || two == null)
{
throw new IllegalArgumentException("Parameters can't be null");
}
//...
}
}
Run Code Online (Sandbox Code Playgroud)
这里的异常让你知道哪个参数为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");
}
//...
}
Run Code Online (Sandbox Code Playgroud)
这里构造函数更整洁,但现在构造函数代码实际上不在构造函数中:
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");
}
//...
}
}
Run Code Online (Sandbox Code Playgroud)
哪种款式最好?
或者是否有更广泛接受的替代方案?
Boz*_*zho 91
第二或第三.
因为它告诉用户你的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");
...
}
Run Code Online (Sandbox Code Playgroud)
将支票放入设定者也是可以接受的,具有相同的详细程度评论.如果您的setter还具有保持对象一致性的角色,您也可以选择第三个.
pol*_*nts 38
您可以使用众多库中的一个来促进前置条件检查.Google Guava中的许多代码都使用com.google.common.base.Preconditions
在您自己的方法开始时调用的简单静态方法,以验证正确的参数和状态.这允许诸如的构造
Run Code Online (Sandbox Code Playgroud)if (count <= 0) { throw new IllegalArgumentException("must be positive: " + count); }被更紧凑的替换
Run Code Online (Sandbox Code Playgroud)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!");
//...
}
Run Code Online (Sandbox Code Playgroud)
大多数方法都被重载为不带错误消息,固定错误消息或带有varargs的模板化错误消息.
IllegalArgumentExceptionvsNullPointerException当你的原始代码抛出IllegalArgumentException的null论点,番石榴的Preconditions.checkNotNull抛出NullPointerException来代替.
以下是Effective Java 2nd Edition的引用:第60项:支持使用标准异常:
可以说,所有错误的方法调用归结为非法论证或非法国家,但其他例外标准地用于某些类型的非法论证和状态.如果调用者传入
null一些禁止空值的参数,则会NullPointerException抛出约定而不是IllegalArgumentException.
NullPointerException当您访问null引用的成员时,不保留A ; 当参数是null非法值时抛出它们是非常标准的.
System.out.println("some string".split(null));
// throws NullPointerException
Run Code Online (Sandbox Code Playgroud)
Gho*_*ica 38
老问题; 另一个新的答案(另一个评论已经提到过;但我觉得值得自己回答).
Java 7添加java.lang.Objects.requireNonNull()到每个人都可以使用的API中.因此,检查null的所有参数可以归结为一个简短的列表,如:
this.arg1 = Objects.requireNonNull(arg1, "arg1 must not be null");
this.arg2 = Objects.requireNonNull(arg2, "arg2 must not be null");
Run Code Online (Sandbox Code Playgroud)
附注:
我会有一个实用方法:
public static <T> T checkNull(String message, T object) {
if(object == null) {
throw new NullPointerException(message);
}
return object;
}
Run Code Online (Sandbox Code Playgroud)
我会让它返回对象,以便您可以在这样的分配中使用它:
public Constructor(Object param) {
this.param = checkNull("Param not allowed to be null", param);
}
Run Code Online (Sandbox Code Playgroud)
编辑:关于使用第三方库的建议,特别是 Google Preconditions 比我的代码做得更好。但是,如果这是将库包含在您的项目中的唯一原因,我会犹豫不决。方法太简单了。