Using @NotNull on a Method Parameter – 在方法参数上使用@NotNull

最后修改: 2022年 7月 18日

1. Overview


NullPointerExceptions are a common problem. One way we can protect our code is to add annotations such as @NotNull to our method parameters.


By using @NotNull, we indicate that we must never call our method with a null if we want to avoid an exception. However, by itself, that’s not enough. Let’s learn why.


2. @NotNull Annotation on a Method Parameter


First, let’s create a class with a method that simply returns the length of a String.


Let’s also add a @NotNull annotation to our parameter:


public class NotNullMethodParameter {
    public int validateNotNull(@NotNull String data) {
        return data.length();

When we import NotNull, we should note that there are several implementations of a @NotNull annotation. So, we need to make sure that it’s from the right package.


We’ll use the javax.validation.constraints package.


Now, let’s create a NotNullMethodParameter and call our method with a null parameter:


NotNullMethodParameter notNullMethodParameter = new NotNullMethodParameter();

Despite our NotNull annotation, we get a NullPointerException:



Our annotation has no effect because there’s no validator to enforce it.


3. Adding a Validator


So, let’s add Hibernate Validator, the javax.validation reference implementation, to recognize our @NotNull.

所以,让我们添加Hibernate Validator,javax.validation参考实现,来识别我们的@NotNull

Besides our validator, we also need to add a dependency for the expression language (EL) that it uses for rendering messages:




When we don’t include the EL dependency, we get a ValidationException to remind us:


javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead

With our dependencies in place, we can enforce our @NotNull annotation.


So, let’s create a validator using the default ValidatorFactory:


ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

And then, let’s validate our argument as the first line of our annotated method:



Now, when we call our method with a null parameter, our @NotNull is enforced:


java.lang.IllegalArgumentException: HV000116: The object to be validated must not be null.

This is great, but having to add a call to our validator inside every annotated method results in a lot of boilerplate.


4. Spring Boot


Fortunately, there’s a much simpler approach that we can use in our Spring Boot applications.

幸运的是,有一种更简单的方法,我们可以在我们的Spring Boot应用程序中使用。

4.1. Spring Boot Validation

4.1.Spring Boot验证

First, let’s add the Maven dependency for validation with Spring Boot:

首先,让我们添加Maven依赖性,以便用Spring Boot进行验证。


Our spring-boot-starter-validation dependency brings in all we need for Spring Boot and validation. This means that we can remove our earlier Hibernate and EL dependencies to keep our pom.xml clean.

我们的spring-boot-starter-validation依赖性带来了我们所需要的Spring Boot和验证。这意味着我们可以删除之前的Hibernate和EL依赖,以保持我们的pom.xml干净。

Now, let’s create a Spring-managed Component, ensuring we add the @Validated annotation. Let’s create it with a validateNotNull method that takes a String parameter and returns the length of our data, and annotate our parameter with @NotNull:

现在,让我们创建一个Spring管理的Component确保我们添加了@Validated 注释。让我们用一个validateNotNull方法来创建它,该方法接收一个String参数并返回数据的长度,并用@NotNull来注释我们的参数。

public class ValidatingComponent {
    public int validateNotNull(@NotNull String data) {
        return data.length();

Finally, let’s create a SpringBootTest with our ValidatingComponent autowired in. Let’s also add a test with null as a method parameter:


class ValidatingComponentTest {
    @Autowired ValidatingComponent component;

    void givenNull_whenValidate_thenConstraintViolationException() {
        assertThrows(ConstraintViolationException.class, () -> component.validate(null));

The ConstraintViolationException that we get has our parameter name and a ‘must not be null’ message:

我们得到的ConstraintViolationException有我们的参数名称和一个 “不得为空 “的消息

javax.validation.ConstraintViolationException: must not be null

We can learn more about annotating our methods in our method constraints article.

我们可以在method constraints文章中了解更多关于注释我们的方法的信息。

4.2. A Cautionary Word


Although this works for our public method, let’s see what happens when we add another method that isn’t annotated but that calls our original annotated method:


public String callAnnotatedMethod(String data) {
    return validateNotNull(data);

Our NullPointerException returns. Spring doesn’t enforce NotNull constraints when we invoke the annotated method from another method that resides in the same class.


4.3. Jakarta and Spring Boot 3.0

4.3.雅加达和Spring Boot 3.0

With Jakarta, the validation package names recently changed from javax.validation to jakarta.validation. Spring Boot 3.0 is based on Jakarta and so uses the newer jakarta.validation packages. This is also the case for versions of hibernate-validator from 7.0.* and onwards. This means that when we upgrade, we’ll need to change the package names we use in our validation annotations.

通过Jakarta,验证包的名称最近从javax.validation变为jakarta.validationSpring Boot 3.0 基于 Jakarta,因此使用较新的jakarta.validation包。7.0.*及以上版本的hibernate-validator也是如此。这意味着,当我们升级时,我们需要改变我们在验证注释中使用的包名。

5. Conclusion


In this article, we learned how to use the @NotNull annotation on a method parameter in a standard Java application. We also learned how to use Spring Boot’s @Validated annotation to simplify our Spring Bean method parameter validation while also noting its limitations. Finally, we noted that we should expect to change our javax packages to jakarta when we update our Spring Boot projects to 3.0.

在这篇文章中,我们学习了如何在标准Java应用程序中的方法参数上使用@NotNull注解。我们还学习了如何使用Spring Boot的@Validated注解来简化我们的Spring Bean方法参数验证,同时也注意到它的局限性。最后,我们注意到,当我们将Spring Boot项目更新到3.0时,我们应该将javax包改为jakarta

As usual, all the code samples shown in this article are available over on GitHub.