本文要讲解的是怎样声明方法约束。
首先,我们要明白什么是方法约束:其实就是对方法的参数和返回值进行约束,这里说的方法包括构造方法。下面这个例子就是方法约束,更准确地说,它是参数约束。
public class RentalStation {
// 构造方法
public RentalStation(@NotNull String name) {}
// 普通方法
public void rentCar(@NotNull Customer customer, @NotNull @Future Date startDate,
@Min(1) int durationInDays) {}
private class Customer {
}
}
我们可以把参数约束看做是一种前置条件,方法的调用者必须先满足参数约束,该方法才能被成功调用;而返回值约束可以看做是一种后置条件,方法的返回值必须满足这些约束。
需要注意的是,参数约束只能用于实例方法。比如说,类中静态方法就不能应用参数约束。
有时候,我们可能不仅仅是对单个参数进行约束,而是需要对多个参数同时进行约束,也就是跨参数约束,这种情况也是支持的。
可以拿跨参数约束和类级别的约束比较一下。相同点是二者都基于多个元素。不同的是,后者作用于类,约束对象是类的属性;而前者作用于方法,约束对象是方法的参数。看下面这个例子:
该方法有2个参数,第一代表乘客,第二个代表行李,我们使用跨参数约束LuggageCountMatchesPassengerCount来限制每个乘客不能携带超过两件的行李。(具体怎么实现不是本文要讲的)
从上面我们可以看出来,对单个参数进行约束的时候,我们的约束(注解)是写在参数前边的;而跨参数约束则是写在方法签名上面的。
其实,返回值约束(文末有例子)也是写在方法签名上面的。那么,我们怎么区分一个约束是跨参数约束还是返回值约束呢?此时,需要为约束指定validationAppliesTo属性。看例子:
同时也可以看一下validation-api对ValidationTarget的定义:
public enum ValidationTarget {
/**
* (Returned) element annotated by the constraint.
*/
ANNOTATED_ELEMENT,
/**
* Array of parameters of the annotated method or constructor (aka cross-parameter).
*/
PARAMETERS
}
承上,其实多数情况下,约束的应用目标是可以自动推断出来的(此时可以省略validationAppliesTo属性)。比如:
- 返回值是void但是有参数,此时自然是对参数进行约束;
- 返回值不是void但是没有参数,此时自然是对返回值进行约束;
但是为了代码的可读性,还是建议加上validationAppliesTo属性
文章开头看了参数约束的例子,结尾的时候看一个返回值约束的例子,比较一下。