[java] 메소드 인수에서 NotNull 어노테이션 사용

방금 @NotNullJava 8 에서 주석을 사용하고 예기치 않은 결과를 얻었습니다.

다음과 같은 방법이 있습니다.

public List<Found> findStuff(@NotNull List<Searching> searchingList) {
    ... code here ...
}

searchList 인수에 대해 null 값을 전달하는 JUnit 테스트를 작성했습니다. 어떤 유형의 오류가 발생할 것으로 예상했지만 주석이없는 것처럼 진행되었습니다. 이것이 예상되는 동작입니까? 내가 이해 한 바에 따르면, 상용구 null 확인 코드 작성을 건너 뛸 수 있습니다.

@NotNull이 정확히 무엇을하는지에 대한 설명은 크게 감사하겠습니다.



답변

@Nullable그리고 @NotNull아무것도하지 마십시오. 그것들은 문서 도구로 작용해야합니다.

@Nullable주석이 때 NPE 확인을 소개하는 필요성에 대해 생각 나게한다 :

  1. null을 돌려주는 메소드 호출
  2. null 일 수있는 역 참조 변수 (필드, 로컬 변수, 매개 변수)

@NotNull주석 실제로, 다음을 선언하는 명시 적 계약이다 :

  1. 메소드는 널을 리턴해서는 안됩니다.
  2. (필드, 로컬 변수, 파라미터 등) 변수는 없다 NULL 값을 잡아.

예를 들어, 쓰는 대신 :

/**
 * @param aX should not be null
 */
public void setX(final Object aX ) {
    // some code
}

당신이 사용할 수있는:

public void setX(@NotNull final Object aX ) {
    // some code
}

또한, @NotNull자주에 의해 확인된다 ConstraintValidators (봄에 예를 들어.와 최대 절전 모드).

@NotNull때문에 주석은 자신이 검증하지 않는다는 주석 정의가 어떤 제공하지 않습니다 ConstraintValidator유형 참조.

자세한 내용은 다음을 참조하십시오.

  1. 빈 검증
  2. NotNull.java
  3. 제약 사항 .java
  4. ConstraintValidator.java

답변

위에서 언급했듯이 @NotNull자체적으로 아무것도하지 않습니다. 사용하는 좋은 방법은 @NotNull그것을 사용하는 것Objects.requireNonNull

public class Foo {
    private final Bar bar;

    public Foo(@NotNull Bar bar) {
        this.bar = Objects.requireNonNull(bar, "bar must not be null");
    }
}


답변

@NotNull활성화 하려면 롬복이 필요합니다.

https://projectlombok.org/features/NonNull

import lombok.NonNull;

따르십시오 : 어떤 @NotNull Java 주석을 사용해야합니까?


답변

@NotNull은 태그 일뿐입니다 … 유효성을 확인하려면 최대 절전 모드 유효성 검사기 jsr 303과 같은 것을 사용해야합니다

ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
 Set<ConstraintViolation<List<Searching>> violations = validator.validate(searchingList);


답변

Spring을 사용하는 경우 다음과 같이 클래스에 주석을 달아 유효성 검사를 강제 실행할 수 있습니다 @Validated.

import org.springframework.validation.annotation.Validated;

자세한 정보는 여기 :
Javax 유효성 검사 @NotNull 주석 사용법


답변

내 자신의 유효성 검사 주석과 유효성 검사기를 만들려면 다음과 같이하십시오.

ValidCardType.java(방법 / 분야에 대한 주석)

@Constraint(validatedBy = {CardTypeValidator.class})
@Documented
@Target( { ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidCardType {
    String message() default "Incorrect card type, should be among: \"MasterCard\" | \"Visa\"";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

그리고 검사기가 검사를 시작합니다.
CardTypeValidator.java:

public class CardTypeValidator implements ConstraintValidator<ValidCardType, String> {
    private static final String[] ALL_CARD_TYPES = {"MasterCard", "Visa"};

    @Override
    public void initialize(ValidCardType status) {
    }
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return (Arrays.asList(ALL_CARD_TYPES).contains(value));
    }
}

check와 매우 비슷한 것을 할 수 있습니다 @NotNull.


답변

테스트에서 메소드 유효성 검증을 테스트하려면 @Before 메소드에서 프록시를 랩핑해야합니다.

@Before
public void setUp() {
    this.classAutowiredWithFindStuffMethod = MethodValidationProxyFactory.createProxy(this.classAutowiredWithFindStuffMethod);
}

MethodValidationProxyFactory를 다음과 같이 사용하십시오.

import org.springframework.context.support.StaticApplicationContext;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

public class MethodValidationProxyFactory {

private static final StaticApplicationContext ctx = new StaticApplicationContext();

static {
    MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
    processor.afterPropertiesSet(); // init advisor
    ctx.getBeanFactory()
            .addBeanPostProcessor(processor);
}

@SuppressWarnings("unchecked")
public static <T> T createProxy(T instance) {

    return (T) ctx.getAutowireCapableBeanFactory()
            .applyBeanPostProcessorsAfterInitialization(instance, instance.getClass()
                    .getName());
}

}

그런 다음 테스트를 추가하십시오.

@Test
public void findingNullStuff() {
 assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> this.classAutowiredWithFindStuffMethod.findStuff(null));

}