[java] 메소드 인수에서 NotNull 어노테이션 사용
방금 @NotNull
Java 8 에서 주석을 사용하고 예기치 않은 결과를 얻었습니다.
다음과 같은 방법이 있습니다.
public List<Found> findStuff(@NotNull List<Searching> searchingList) {
... code here ...
}
searchList 인수에 대해 null 값을 전달하는 JUnit 테스트를 작성했습니다. 어떤 유형의 오류가 발생할 것으로 예상했지만 주석이없는 것처럼 진행되었습니다. 이것이 예상되는 동작입니까? 내가 이해 한 바에 따르면, 상용구 null 확인 코드 작성을 건너 뛸 수 있습니다.
@NotNull이 정확히 무엇을하는지에 대한 설명은 크게 감사하겠습니다.
답변
@Nullable
그리고 @NotNull
아무것도하지 마십시오. 그것들은 문서 도구로 작용해야합니다.
@Nullable
주석이 때 NPE 확인을 소개하는 필요성에 대해 생각 나게한다 :
- null을 돌려주는 메소드 호출
- null 일 수있는 역 참조 변수 (필드, 로컬 변수, 매개 변수)
@NotNull
주석 실제로, 다음을 선언하는 명시 적 계약이다 :
- 메소드는 널을 리턴해서는 안됩니다.
- (필드, 로컬 변수, 파라미터 등) 변수는
없다안 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
유형 참조.
자세한 내용은 다음을 참조하십시오.
답변
위에서 언급했듯이 @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));
}