如果您使用的是 Java 8,则可以使用 lambdas 创建一个非常优雅且可读的验证解决方案:
public class Assert {
public interface CheckArgument<O> {
boolean test(O object);
}
public static final <O> O that(O argument, CheckArgument<O> check) {
if (!check.test(argument))
throw new IllegalArgumentException("Illegal argument: " + argument);
return argument;
}
}
你像这样使用它:
public void setValue(int value) {
this.value = Assert.that(value, arg -> arg >= 0);
}
异常将如下所示:
Exception in thread "main" java.lang.IllegalArgumentException: Illegal argument: -7
at com.xyz.util.Assert.that(Assert.java:13)
at com.xyz.Main.main(Main.java:16)
第一个好处是上面的 Assert 类是真正需要的:
public void setValue(String value) {
this.value = Assert.that(value, arg -> arg != null && !arg.trim().isEmpty());
}
public void setValue(SomeObject value) {
this.value = Assert.that(value, arg -> arg != null && arg.someTest());
}
当然that()
可以通过多种方式实现:使用格式字符串和参数,抛出其他类型的异常等。
然而,它并不需要被实现来执行不同的测试。
并不是说如果您愿意,您就不能预先打包测试:
public static CheckArgument<Object> isNotNull = arg -> arg != null;
Assert.that(x, Assert.isNotNull);
// with a static import:
Assert.that(x, isNotNull);
我不知道这是否对性能不利或出于其他原因不是一个好主意。(我自己刚开始研究 lambda,但代码似乎运行正常......)但我喜欢它Assert
可以保持简短(不需要对项目可能不重要的依赖项)并且测试非常可见。
这是一个更好的错误消息的方法:
public static final <O> O that(O argument, CheckArgument<O> check,
String format, Object... objects)
{
if (!check.test(argument))
throw new IllegalArgumentException(
String.format(format, objects));
return argument;
}
你这样称呼它:
public void setValue(String value) {
this.value = Assert.that(value,
arg -> arg != null && arg.trim().isEmpty(),
"String value is empty or null: %s", value);
}
出来了:
Exception in thread "main" java.lang.IllegalArgumentException: String value is empty or null: null
at com.xyz.util.Assert.that(Assert.java:21)
at com.xyz.Main.main(Main.java:16)
更新:如果您想将x = Assert...
构造与预打包测试一起使用,结果将被转换为预打包测试中使用的类型。所以它必须被转换回变量的类型......SomeClass x = (SomeClass) Assert.that(x, isNotNull)