Verwendung der NotNull-Annotation im Methodenargument

Lesezeit: 5 Minuten

Ich habe gerade angefangen, die zu verwenden @NotNull Anmerkung mit Java 8 und einige unerwartete Ergebnisse erhalten.

Ich habe eine Methode wie diese:

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

Ich habe einen JUnit-Test geschrieben, der den Nullwert für das Argument searchList übergibt. Ich hatte erwartet, dass ein Fehler auftritt, aber es ging durch, als ob die Anmerkung nicht vorhanden wäre. Ist das erwartetes Verhalten? Soweit ich verstanden habe, sollten Sie damit das Schreiben des Boilerplate-Null-Check-Codes überspringen.

Eine Erklärung, was genau @NotNull tun soll, wäre sehr willkommen.

  • @NotNull ist nur eine anmerkung. Anmerkungen allein tun nichts. Sie benötigen zur Kompilierzeit einen Anmerkungsprozessor oder etwas, das ihn zur Laufzeit verarbeitet.

    – Sotirios Delimanolis

    4. Dezember 2015 um 17:30 Uhr

  • Führen Sie den Code innerhalb eines Anwendungsservers aus (z. B. mit Arquillian)?

    – jabu.10245

    4. Dezember 2015 um 17:34 Uhr

  • @SotiriosDelimanolis – Was ist dann der Sinn, nur eine Warnung an alle, die die Methode aufrufen, keinen Nullwert zu übergeben? In diesem Fall benötigen Sie immer noch den Nullzeiger-Validierungscode.

    – DavidR

    4. Dezember 2015 um 17:34 Uhr

  • Schauen Sie sich den Hibernate-Validator an

    – Arisalexis

    4. Dezember 2015 um 17:36 Uhr

  • @jabu.10245 – Es wird kein Anwendungsserver verwendet.

    – DavidR

    4. Dezember 2015 um 17:36 Uhr

Benutzer-Avatar
Lukas Oliveira

@Nullable und @NotNull nichts selber machen. Sie sollen als Dokumentationswerkzeuge fungieren.

Das @Nullable Die Anmerkung erinnert Sie an die Notwendigkeit, eine NPE-Prüfung einzuführen, wenn:

  1. Aufrufen von Methoden, die null zurückgeben können.
  2. Dereferenzieren von Variablen (Felder, lokale Variablen, Parameter), die null sein können.

Das @NotNull Annotation ist eigentlich ein ausdrücklicher Vertrag, der Folgendes erklärt:

  1. Eine Methode sollte nicht null zurückgeben.
  2. Eine Variable (wie Felder, lokale Variablen und Parameter) kann nicht sollte nicht Nullwert halten.

Anstatt z.B. zu schreiben:

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

Sie können Folgendes verwenden:

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

Zusätzlich, @NotNull wird oft von überprüft ConstraintValidators (z. B. im Frühjahr und Winterschlaf).

Das @NotNull Annotation führt keine eigene Validierung durch, da die Anmerkungsdefinition liefert keine ConstraintValidator Typ Referenz.

Weitere Informationen finden Sie unter:

  1. Bean-Validierung
  2. NotNull.java
  3. Einschränkung.java
  4. ConstraintValidator.java

  • Nur um Teil 2 des NotNull-Teils zu verdeutlichen, sollte es wirklich heißen “sollte nicht”, nicht “kann”, da es nicht erzwungen werden kann? Oder wenn es zur Laufzeit erzwungen werden kann, wie würden Sie vorgehen?

    – DavidR

    4. Dezember 2015 um 20:57 Uhr

  • Ja, es ist ein “sollte nicht” … die Methodenimplementierung sollte den Vertrag durchsetzen.

    – Lukas Oliveira

    7. Dezember 2015 um 15:35 Uhr

  • Alternativ in Java 8, Optional könnte anstelle von verwendet werden @Null in Rückgabewerten und Methodenüberladung anstelle von @Null in Parameterlisten: dolszewski.com/java/java-8-optional-use-cases

    – Tschad K

    18. Juli 2017 um 21:56 Uhr

  • Ich glaube, die Verwirrung kommt von der Java-Dokumentation der NotNull-Anmerkung: * The annotated element must not be {@code null}. * Accepts any type. und ich denke muss Wort sollte durch ersetzt werden sollte aber auch hier kommt es darauf an, wie man es liest. Auf jeden Fall wären weitere Klarstellungen gut

    – Julian

    19. Juli 2017 um 22:58 Uhr

  • @Julian ‘muss nicht’ scheint richtig zu sein. Es darf nicht null enthalten, da der Aufruf sonst wahrscheinlich nicht funktioniert oder fehlerhafte Ergebnisse liefert. ‘cannot’ würde anzeigen, dass es abgelehnt wird, was korrekt wäre, wenn die Anmerkung es erzwingen würde, was nicht der Fall ist. Die verwendete Terminologie scheint also korrekt zu sein.

    – Frank Hopkins

    30. Juli 2020 um 7:15 Uhr

Benutzer-Avatar
Bollywood

Wie oben erwähnt @NotNull macht nichts von alleine. Eine gute Art der Verwendung @NotNull würde es mit verwenden Objects.requireNonNull

public class Foo {
    private final Bar bar;

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

  • Wenn das Balkenfeld mit NotNull annotiert wurde, würde der Aufruf von Objects.requireNonNull immer noch eine Warnung generieren, da die Methode requireNonNull keine NotNull-Referenz zurückgibt.

    – cquezel

    16. April 2021 um 14:19 Uhr

  • Ich brauche das !!!

    – Normidar

    20. Juli um 5:58 Uhr

Benutzer-Avatar
gegebenkoa

Zu machen @NonNull aktiv brauchst du Lombok:

https://projectlombok.org/features/NonNull

import lombok.NonNull;

Folgen Sie: Welche @NotNull-Java-Annotation soll ich verwenden?

SO @NotNull ist nur ein Tag … Wenn Sie es validieren möchten, müssen Sie so etwas wie Hibernate Validator jsr 303 verwenden

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

Benutzer-Avatar
sisanared

Wenn Sie Spring verwenden, können Sie die Validierung erzwingen, indem Sie die Klasse mit kommentieren @Validated:

import org.springframework.validation.annotation.Validated;

Weitere Informationen finden Sie hier: Verwendung der Javax @NotNull-Anmerkung

Könntest du auch verwenden @NonNull aus projectlombok (lombok.NonNull)

Benutzer-Avatar
WesternGun

Ich tue dies, um meine eigene Validierungsanmerkung und meinen eigenen Validator zu erstellen:

ValidCardType.java(Anmerkung zum Anbringen von Methoden/Feldern)

@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 {};
}

Und der Validator zum Auslösen der Prüfung:
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));
    }
}

Sie können etwas sehr ähnliches tun, um dies zu überprüfen @NotNull.

Um Ihre Methodenvalidierung in einem Test zu testen, müssen Sie einen Proxy in die @Before-Methode einschließen.

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

Mit MethodValidationProxyFactory als:

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());
}

}

Und dann fügen Sie Ihren Test hinzu:

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

}

1355080cookie-checkVerwendung der NotNull-Annotation im Methodenargument

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy